]> git.sur5r.net Git - u-boot/blob - board/mx1fs2/flash.c
Rewrite of NAND code based on what is in 2.6.12 Linux kernel
[u-boot] / board / mx1fs2 / flash.c
1 /*
2  * (C) 2000-2004 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
3  * (C) 2003 August Hoeraendl, Logotronic GmbH
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 #undef CONFIG_FLASH_16BIT
25
26 #include <common.h>
27
28 #if defined CFG_JFFS_CUSTOM_PART
29 #include <jffs2/jffs2.h>
30 #endif
31
32 #define FLASH_BANK_SIZE MX1FS2_FLASH_BANK_SIZE
33 #define MAIN_SECT_SIZE  MX1FS2_FLASH_SECT_SIZE
34
35 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips   */
36
37 /*
38  * NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
39  *        has nothing to do with the flash chip being 8-bit or 16-bit.
40  */
41 #ifdef CONFIG_FLASH_16BIT
42 typedef unsigned short FLASH_PORT_WIDTH;
43 typedef volatile unsigned short FLASH_PORT_WIDTHV;
44
45 #define FLASH_ID_MASK   0xFFFF
46 #else
47 typedef unsigned long FLASH_PORT_WIDTH;
48 typedef volatile unsigned long FLASH_PORT_WIDTHV;
49
50 #define FLASH_ID_MASK   0xFFFFFFFF
51 #endif
52
53 #define FPW     FLASH_PORT_WIDTH
54 #define FPWV    FLASH_PORT_WIDTHV
55
56 #define ORMASK(size) ((-size) & OR_AM_MSK)
57
58 /*-----------------------------------------------------------------------
59  * Functions
60  */
61 #if 0
62 static ulong flash_get_size(FPWV * addr, flash_info_t * info);
63 static void flash_get_offsets(ulong base, flash_info_t * info);
64 #endif
65 static void flash_reset(flash_info_t * info);
66 static int write_word_intel(flash_info_t * info, FPWV * dest, FPW data);
67 static int write_word_amd(flash_info_t * info, FPWV * dest, FPW data);
68 #define write_word(in, de, da)   write_word_amd(in, de, da)
69 #ifdef CFG_FLASH_PROTECTION
70 static void flash_sync_real_protect(flash_info_t * info);
71 #endif
72
73 #if defined CFG_JFFS_CUSTOM_PART
74
75 /**
76  * jffs2_part_info - get information about a JFFS2 partition
77  *
78  * @part_num: number of the partition you want to get info about
79  * @return:   struct part_info* in case of success, 0 if failure
80  */
81
82 static struct part_info part;
83 static int current_part = -1;
84
85 struct part_info *
86 jffs2_part_info(int part_num)
87 {
88         void *jffs2_priv_saved = part.jffs2_priv;
89
90         printf("jffs2_part_info: part_num=%i\n", part_num);
91
92         if (current_part == part_num)
93                 return &part;
94
95         /* rootfs                                                 */
96         if (part_num == 0) {
97                 memset(&part, 0, sizeof (part));
98
99                 part.offset = (char *) MX1FS2_JFFS2_PART0_START;
100                 part.size = MX1FS2_JFFS2_PART0_SIZE;
101
102                 /* Mark the struct as ready */
103                 current_part = part_num;
104
105                 printf("part.offset = 0x%08x\n", (unsigned int) part.offset);
106                 printf("part.size   = 0x%08x\n", (unsigned int) part.size);
107         }
108
109         /* userfs                                    */
110         if (part_num == 1) {
111                 memset(&part, 0, sizeof (part));
112
113                 part.offset = (char *) MX1FS2_JFFS2_PART1_START;
114                 part.size = MX1FS2_JFFS2_PART1_SIZE;
115
116                 /* Mark the struct as ready */
117                 current_part = part_num;
118
119                 printf("part.offset = 0x%08x\n", (unsigned int) part.offset);
120                 printf("part.size   = 0x%08x\n", (unsigned int) part.size);
121         }
122
123         if (current_part == part_num) {
124                 part.usr_priv = &current_part;
125                 part.jffs2_priv = jffs2_priv_saved;
126                 return &part;
127         }
128
129         printf("jffs2_part_info: end of partition table\n");
130         return 0;
131 }
132 #endif                          /* CFG_JFFS_CUSTOM_PART */
133
134 /*-----------------------------------------------------------------------
135  * flash_init()
136  *
137  * sets up flash_info and returns size of FLASH (bytes)
138  */
139 ulong
140 flash_init(void)
141 {
142         int i, j;
143         ulong size = 0;
144
145         for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
146                 ulong flashbase = 0;
147                 flash_info[i].flash_id =
148                     (FLASH_MAN_AMD & FLASH_VENDMASK) |
149                     (FLASH_AM640U & FLASH_TYPEMASK);
150                 flash_info[i].size = FLASH_BANK_SIZE;
151                 flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
152                 memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
153                 switch (i) {
154                 case 0:
155                         flashbase = MX1FS2_FLASH_BASE;
156                         break;
157                 default:
158                         panic("configured too many flash banks!\n");
159                         break;
160                 }
161                 for (j = 0; j < flash_info[i].sector_count; j++) {
162                         flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE;
163                 }
164                 size += flash_info[i].size;
165         }
166
167         /* Protect monitor and environment sectors */
168         flash_protect(FLAG_PROTECT_SET,
169                       CFG_FLASH_BASE,
170                       CFG_FLASH_BASE + _bss_start - _armboot_start,
171                       &flash_info[0]);
172
173         flash_protect(FLAG_PROTECT_SET,
174                       CFG_ENV_ADDR,
175                       CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
176
177         return size;
178 }
179
180 /*-----------------------------------------------------------------------
181  */
182 static void
183 flash_reset(flash_info_t * info)
184 {
185         FPWV *base = (FPWV *) (info->start[0]);
186
187         /* Put FLASH back in read mode */
188         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
189                 *base = (FPW) 0x00FF00FF;       /* Intel Read Mode */
190         else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
191                 *base = (FPW) 0x00F000F0;       /* AMD Read Mode */
192 }
193
194 /*-----------------------------------------------------------------------
195  */
196 #if 0
197 static void
198 flash_get_offsets(ulong base, flash_info_t * info)
199 {
200         int i;
201
202         /* set up sector start address table */
203         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
204             && (info->flash_id & FLASH_BTYPE)) {
205                 int bootsect_size;      /* number of bytes/boot sector  */
206                 int sect_size;  /* number of bytes/regular sector */
207
208                 bootsect_size = 0x00002000 * (sizeof (FPW) / 2);
209                 sect_size = 0x00010000 * (sizeof (FPW) / 2);
210
211                 /* set sector offsets for bottom boot block type        */
212                 for (i = 0; i < 8; ++i) {
213                         info->start[i] = base + (i * bootsect_size);
214                 }
215                 for (i = 8; i < info->sector_count; i++) {
216                         info->start[i] = base + ((i - 7) * sect_size);
217                 }
218         } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
219                    && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
220
221                 int sect_size;  /* number of bytes/sector */
222
223                 sect_size = 0x00010000 * (sizeof (FPW) / 2);
224
225                 /* set up sector start address table (uniform sector type) */
226                 for (i = 0; i < info->sector_count; i++)
227                         info->start[i] = base + (i * sect_size);
228         }
229 }
230 #endif /* 0 */
231
232 /*-----------------------------------------------------------------------
233  */
234
235 void
236 flash_print_info(flash_info_t * info)
237 {
238         int i;
239         uchar *boottype;
240         uchar *bootletter;
241         uchar *fmt;
242         uchar botbootletter[] = "B";
243         uchar topbootletter[] = "T";
244         uchar botboottype[] = "bottom boot sector";
245         uchar topboottype[] = "top boot sector";
246
247         if (info->flash_id == FLASH_UNKNOWN) {
248                 printf("missing or unknown FLASH type\n");
249                 return;
250         }
251
252         switch (info->flash_id & FLASH_VENDMASK) {
253         case FLASH_MAN_AMD:
254                 printf("AMD ");
255                 break;
256         case FLASH_MAN_BM:
257                 printf("BRIGHT MICRO ");
258                 break;
259         case FLASH_MAN_FUJ:
260                 printf("FUJITSU ");
261                 break;
262         case FLASH_MAN_SST:
263                 printf("SST ");
264                 break;
265         case FLASH_MAN_STM:
266                 printf("STM ");
267                 break;
268         case FLASH_MAN_INTEL:
269                 printf("INTEL ");
270                 break;
271         default:
272                 printf("Unknown Vendor ");
273                 break;
274         }
275
276         /* check for top or bottom boot, if it applies */
277         if (info->flash_id & FLASH_BTYPE) {
278                 boottype = botboottype;
279                 bootletter = botbootletter;
280         } else {
281                 boottype = topboottype;
282                 bootletter = topbootletter;
283         }
284
285         switch (info->flash_id & FLASH_TYPEMASK) {
286         case FLASH_AM640U:
287                 fmt = "29LV641D (64 Mbit, uniform sectors)\n";
288                 break;
289         case FLASH_28F800C3B:
290         case FLASH_28F800C3T:
291                 fmt = "28F800C3%s (8 Mbit, %s)\n";
292                 break;
293         case FLASH_INTEL800B:
294         case FLASH_INTEL800T:
295                 fmt = "28F800B3%s (8 Mbit, %s)\n";
296                 break;
297         case FLASH_28F160C3B:
298         case FLASH_28F160C3T:
299                 fmt = "28F160C3%s (16 Mbit, %s)\n";
300                 break;
301         case FLASH_INTEL160B:
302         case FLASH_INTEL160T:
303                 fmt = "28F160B3%s (16 Mbit, %s)\n";
304                 break;
305         case FLASH_28F320C3B:
306         case FLASH_28F320C3T:
307                 fmt = "28F320C3%s (32 Mbit, %s)\n";
308                 break;
309         case FLASH_INTEL320B:
310         case FLASH_INTEL320T:
311                 fmt = "28F320B3%s (32 Mbit, %s)\n";
312                 break;
313         case FLASH_28F640C3B:
314         case FLASH_28F640C3T:
315                 fmt = "28F640C3%s (64 Mbit, %s)\n";
316                 break;
317         case FLASH_INTEL640B:
318         case FLASH_INTEL640T:
319                 fmt = "28F640B3%s (64 Mbit, %s)\n";
320                 break;
321         default:
322                 fmt = "Unknown Chip Type\n";
323                 break;
324         }
325
326         printf(fmt, bootletter, boottype);
327
328         printf("  Size: %ld MB in %d Sectors\n",
329                info->size >> 20, info->sector_count);
330
331         printf("  Sector Start Addresses:");
332
333         for (i = 0; i < info->sector_count; ++i) {
334                 if ((i % 5) == 0) {
335                         printf("\n   ");
336                 }
337
338                 printf(" %08lX%s", info->start[i],
339                        info->protect[i] ? " (RO)" : "     ");
340         }
341
342         printf("\n");
343 }
344
345 /*-----------------------------------------------------------------------
346  */
347
348 /*
349  * The following code cannot be run from FLASH!
350  */
351
352 #if 0
353 ulong
354 flash_get_size(FPWV * addr, flash_info_t * info)
355 {
356         /* Write auto select command: read Manufacturer ID */
357
358         /* Write auto select command sequence and test FLASH answer */
359         addr[0x0555] = (FPW) 0x00AA00AA;        /* for AMD, Intel ignores this */
360         addr[0x02AA] = (FPW) 0x00550055;        /* for AMD, Intel ignores this */
361         addr[0x0555] = (FPW) 0x00900090;        /* selects Intel or AMD */
362
363         /* The manufacturer codes are only 1 byte, so just use 1 byte.
364          * This works for any bus width and any FLASH device width.
365          */
366         switch (addr[0] & 0xff) {
367
368         case (uchar) AMD_MANUFACT:
369                 info->flash_id = FLASH_MAN_AMD;
370                 break;
371
372         case (uchar) INTEL_MANUFACT:
373                 info->flash_id = FLASH_MAN_INTEL;
374                 break;
375
376         default:
377                 info->flash_id = FLASH_UNKNOWN;
378                 info->sector_count = 0;
379                 info->size = 0;
380                 break;
381         }
382
383         /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
384         if (info->flash_id != FLASH_UNKNOWN)
385                 switch (addr[1]) {
386
387                 case (FPW) AMD_ID_LV640U:       /* 29LV640 and 29LV641 have same ID */
388                         info->flash_id += FLASH_AM640U;
389                         info->sector_count = 128;
390                         info->size = 0x00800000 * (sizeof (FPW) / 2);
391                         break;  /* => 8 or 16 MB        */
392
393                 case (FPW) INTEL_ID_28F800C3B:
394                         info->flash_id += FLASH_28F800C3B;
395                         info->sector_count = 23;
396                         info->size = 0x00100000 * (sizeof (FPW) / 2);
397                         break;  /* => 1 or 2 MB         */
398
399                 case (FPW) INTEL_ID_28F800B3B:
400                         info->flash_id += FLASH_INTEL800B;
401                         info->sector_count = 23;
402                         info->size = 0x00100000 * (sizeof (FPW) / 2);
403                         break;  /* => 1 or 2 MB         */
404
405                 case (FPW) INTEL_ID_28F160C3B:
406                         info->flash_id += FLASH_28F160C3B;
407                         info->sector_count = 39;
408                         info->size = 0x00200000 * (sizeof (FPW) / 2);
409                         break;  /* => 2 or 4 MB         */
410
411                 case (FPW) INTEL_ID_28F160B3B:
412                         info->flash_id += FLASH_INTEL160B;
413                         info->sector_count = 39;
414                         info->size = 0x00200000 * (sizeof (FPW) / 2);
415                         break;  /* => 2 or 4 MB         */
416
417                 case (FPW) INTEL_ID_28F320C3B:
418                         info->flash_id += FLASH_28F320C3B;
419                         info->sector_count = 71;
420                         info->size = 0x00400000 * (sizeof (FPW) / 2);
421                         break;  /* => 4 or 8 MB         */
422
423                 case (FPW) INTEL_ID_28F320B3B:
424                         info->flash_id += FLASH_INTEL320B;
425                         info->sector_count = 71;
426                         info->size = 0x00400000 * (sizeof (FPW) / 2);
427                         break;  /* => 4 or 8 MB         */
428
429                 case (FPW) INTEL_ID_28F640C3B:
430                         info->flash_id += FLASH_28F640C3B;
431                         info->sector_count = 135;
432                         info->size = 0x00800000 * (sizeof (FPW) / 2);
433                         break;  /* => 8 or 16 MB        */
434
435                 case (FPW) INTEL_ID_28F640B3B:
436                         info->flash_id += FLASH_INTEL640B;
437                         info->sector_count = 135;
438                         info->size = 0x00800000 * (sizeof (FPW) / 2);
439                         break;  /* => 8 or 16 MB        */
440
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         flash_get_offsets((ulong) addr, info);
449
450         /* Put FLASH back in read mode */
451         flash_reset(info);
452
453         return (info->size);
454 }
455 #endif /* 0 */
456
457 #ifdef CFG_FLASH_PROTECTION
458 /*-----------------------------------------------------------------------
459  */
460
461 static void
462 flash_sync_real_protect(flash_info_t * info)
463 {
464         FPWV *addr = (FPWV *) (info->start[0]);
465         FPWV *sect;
466         int i;
467
468         switch (info->flash_id & FLASH_TYPEMASK) {
469         case FLASH_28F800C3B:
470         case FLASH_28F800C3T:
471         case FLASH_28F160C3B:
472         case FLASH_28F160C3T:
473         case FLASH_28F320C3B:
474         case FLASH_28F320C3T:
475         case FLASH_28F640C3B:
476         case FLASH_28F640C3T:
477                 /* check for protected sectors */
478                 *addr = (FPW) 0x00900090;
479                 for (i = 0; i < info->sector_count; i++) {
480                         /* read sector protection at sector address, (A7 .. A0) = 0x02.
481                          * D0 = 1 for each device if protected.
482                          * If at least one device is protected the sector is marked
483                          * protected, but mixed protected and  unprotected devices
484                          * within a sector should never happen.
485                          */
486                         sect = (FPWV *) (info->start[i]);
487                         info->protect[i] =
488                             (sect[2] & (FPW) (0x00010001)) ? 1 : 0;
489                 }
490
491                 /* Put FLASH back in read mode */
492                 flash_reset(info);
493                 break;
494
495         case FLASH_AM640U:
496         default:
497                 /* no hardware protect that we support */
498                 break;
499         }
500 }
501 #endif
502
503 /*-----------------------------------------------------------------------
504  */
505
506 int
507 flash_erase(flash_info_t * info, int s_first, int s_last)
508 {
509         FPWV *addr;
510         int flag, prot, sect;
511         int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
512         ulong start, now, last;
513         int rcode = 0;
514
515         if ((s_first < 0) || (s_first > s_last)) {
516                 if (info->flash_id == FLASH_UNKNOWN) {
517                         printf("- missing\n");
518                 } else {
519                         printf("- no sectors to erase\n");
520                 }
521                 return 1;
522         }
523
524         switch (info->flash_id & FLASH_TYPEMASK) {
525         case FLASH_INTEL800B:
526         case FLASH_INTEL160B:
527         case FLASH_INTEL320B:
528         case FLASH_INTEL640B:
529         case FLASH_28F800C3B:
530         case FLASH_28F160C3B:
531         case FLASH_28F320C3B:
532         case FLASH_28F640C3B:
533         case FLASH_AM640U:
534                 break;
535         case FLASH_UNKNOWN:
536         default:
537                 printf("Can't erase unknown flash type %08lx - aborted\n",
538                        info->flash_id);
539                 return 1;
540         }
541
542         prot = 0;
543         for (sect = s_first; sect <= s_last; ++sect) {
544                 if (info->protect[sect]) {
545                         prot++;
546                 }
547         }
548
549         if (prot) {
550                 printf("- Warning: %d protected sectors will not be erased!\n",
551                        prot);
552         } else {
553                 printf("\n");
554         }
555
556         start = get_timer(0);
557         last = start;
558
559         /* Start erase on unprotected sectors */
560         for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
561
562                 if (info->protect[sect] != 0)   /* protected, skip it */
563                         continue;
564
565                 /* Disable interrupts which might cause a timeout here */
566                 flag = disable_interrupts();
567
568                 addr = (FPWV *) (info->start[sect]);
569                 if (intel) {
570                         *addr = (FPW) 0x00500050;       /* clear status register */
571                         *addr = (FPW) 0x00200020;       /* erase setup */
572                         *addr = (FPW) 0x00D000D0;       /* erase confirm */
573                 } else {
574                         /* must be AMD style if not Intel */
575                         FPWV *base;     /* first address in bank */
576
577                         base = (FPWV *) (info->start[0]);
578                         base[0x0555] = (FPW) 0x00AA00AA;        /* unlock */
579                         base[0x02AA] = (FPW) 0x00550055;        /* unlock */
580                         base[0x0555] = (FPW) 0x00800080;        /* erase mode */
581                         base[0x0555] = (FPW) 0x00AA00AA;        /* unlock */
582                         base[0x02AA] = (FPW) 0x00550055;        /* unlock */
583                         *addr = (FPW) 0x00300030;       /* erase sector */
584                 }
585
586                 /* re-enable interrupts if necessary */
587                 if (flag)
588                         enable_interrupts();
589
590                 /* wait at least 50us for AMD, 80us for Intel.
591                  * Let's wait 1 ms.
592                  */
593                 udelay(1000);
594
595                 while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
596                         if ((now = get_timer(0)) - start > CFG_FLASH_ERASE_TOUT) {
597                                 printf("Timeout\n");
598
599                                 if (intel) {
600                                         /* suspend erase        */
601                                         *addr = (FPW) 0x00B000B0;
602                                 }
603
604                                 flash_reset(info);      /* reset to read mode */
605                                 rcode = 1;      /* failed */
606                                 break;
607                         }
608
609                         /* show that we're waiting */
610                         if ((now - last) > 1000) {      /* every second */
611                                 putc('.');
612                                 last = now;
613                         }
614                 }
615
616                 flash_reset(info);      /* reset to read mode   */
617         }
618
619         printf(" done\n");
620         return rcode;
621 }
622
623 /*-----------------------------------------------------------------------
624  * Copy memory to flash, returns:
625  * 0 - OK
626  * 1 - write timeout
627  * 2 - Flash not erased
628  */
629 int
630 bad_write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
631 {
632         FPW data = 0;           /* 16 or 32 bit word, matches flash bus width on MPC8XX */
633         int bytes;              /* number of bytes to program in current word         */
634         int left;               /* number of bytes left to program                    */
635         int i, res;
636
637         for (left = cnt, res = 0;
638              left > 0 && res == 0;
639              addr += sizeof (data), left -= sizeof (data) - bytes) {
640
641                 bytes = addr & (sizeof (data) - 1);
642                 addr &= ~(sizeof (data) - 1);
643
644                 /* combine source and destination data so can program
645                  * an entire word of 16 or 32 bits
646                  */
647                 for (i = 0; i < sizeof (data); i++) {
648                         data <<= 8;
649                         if (i < bytes || i - bytes >= left)
650                                 data += *((uchar *) addr + i);
651                         else
652                                 data += *src++;
653                 }
654
655                 /* write one word to the flash */
656                 switch (info->flash_id & FLASH_VENDMASK) {
657                 case FLASH_MAN_AMD:
658                         res = write_word_amd(info, (FPWV *) addr, data);
659                         break;
660                 case FLASH_MAN_INTEL:
661                         res = write_word_intel(info, (FPWV *) addr, data);
662                         break;
663                 default:
664                         /* unknown flash type, error! */
665                         printf("missing or unknown FLASH type\n");
666                         res = 1;        /* not really a timeout, but gives error */
667                         break;
668                 }
669         }
670
671         return (res);
672 }
673
674 /**
675  * write_buf: - Copy memory to flash.
676  *
677  * @param info:
678  * @param src:  source of copy transaction
679  * @param addr: where to copy to
680  * @param cnt:  number of bytes to copy
681  *
682  * @return      error code
683  */
684
685 int
686 write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
687 {
688         ulong cp, wp;
689         FPW data;
690         int l;
691         int i, rc;
692
693         wp = (addr & ~1);       /* get lower word aligned address */
694
695         /* handle unaligned start bytes */
696         if ((l = addr - wp) != 0) {
697                 data = 0;
698                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
699                         data = (data >> 8) | (*(uchar *) cp << 8);
700                 }
701                 for (; i < 2 && cnt > 0; ++i) {
702                         data = (data >> 8) | (*src++ << 8);
703                         --cnt;
704                         ++cp;
705                 }
706                 for (; cnt == 0 && i < 2; ++i, ++cp) {
707                         data = (data >> 8) | (*(uchar *) cp << 8);
708                 }
709
710                 if ((rc = write_word(info, (FPWV *)wp, data)) != 0) {
711                         return (rc);
712                 }
713                 wp += 2;
714         }
715
716         /* handle word aligned part */
717         while (cnt >= 2) {
718                 /* data = *((vushort*)src); */
719                 data = *((FPW *) src);
720                 if ((rc = write_word(info, (FPWV *)wp, data)) != 0) {
721                         return (rc);
722                 }
723                 src += sizeof (FPW);
724                 wp += sizeof (FPW);
725                 cnt -= sizeof (FPW);
726         }
727
728         if (cnt == 0)
729                 return ERR_OK;
730
731         /*
732          * handle unaligned tail bytes
733          */
734         data = 0;
735         for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
736                 data = (data >> 8) | (*src++ << 8);
737                 --cnt;
738         }
739         for (; i < 2; ++i, ++cp) {
740                 data = (data >> 8) | (*(uchar *) cp << 8);
741         }
742
743         return write_word(info, (FPWV *)wp, data);
744 }
745
746 /*-----------------------------------------------------------------------
747  * Write a word to Flash for AMD FLASH
748  * A word is 16 or 32 bits, whichever the bus width of the flash bank
749  * (not an individual chip) is.
750  *
751  * returns:
752  * 0 - OK
753  * 1 - write timeout
754  * 2 - Flash not erased
755  */
756 static int
757 write_word_amd(flash_info_t * info, FPWV * dest, FPW data)
758 {
759         ulong start;
760         int flag;
761         int res = 0;            /* result, assume success       */
762         FPWV *base;             /* first address in flash bank  */
763
764         /* Check if Flash is (sufficiently) erased */
765         if ((*dest & data) != data) {
766                 return (2);
767         }
768
769         base = (FPWV *) (info->start[0]);
770         /* Disable interrupts which might cause a timeout here */
771         flag = disable_interrupts();
772
773         base[0x0555] = (FPW) 0x00AA00AA;        /* unlock */
774         base[0x02AA] = (FPW) 0x00550055;        /* unlock */
775         base[0x0555] = (FPW) 0x00A000A0;        /* selects program mode */
776
777         *dest = data;           /* start programming the data   */
778
779         /* re-enable interrupts if necessary */
780         if (flag)
781                 enable_interrupts();
782
783         start = get_timer(0);
784
785         /* data polling for D7 */
786         while (res == 0
787                && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
788                 if (get_timer(0) - start > CFG_FLASH_WRITE_TOUT) {
789                         *dest = (FPW) 0x00F000F0;       /* reset bank */
790                         printf("SHA timeout\n");
791                         res = 1;
792                 }
793         }
794
795         return (res);
796 }
797
798 /*-----------------------------------------------------------------------
799  * Write a word to Flash for Intel FLASH
800  * A word is 16 or 32 bits, whichever the bus width of the flash bank
801  * (not an individual chip) is.
802  *
803  * returns:
804  * 0 - OK
805  * 1 - write timeout
806  * 2 - Flash not erased
807  */
808 static int
809 write_word_intel(flash_info_t * info, FPWV * dest, FPW data)
810 {
811         ulong start;
812         int flag;
813         int res = 0;            /* result, assume success       */
814
815         /* Check if Flash is (sufficiently) erased */
816         if ((*dest & data) != data) {
817                 return (2);
818         }
819
820         /* Disable interrupts which might cause a timeout here */
821         flag = disable_interrupts();
822
823         *dest = (FPW) 0x00500050;       /* clear status register        */
824         *dest = (FPW) 0x00FF00FF;       /* make sure in read mode       */
825         *dest = (FPW) 0x00400040;       /* program setup                */
826
827         *dest = data;           /* start programming the data   */
828
829         /* re-enable interrupts if necessary */
830         if (flag)
831                 enable_interrupts();
832
833         start = get_timer(0);
834
835         while (res == 0 && (*dest & (FPW) 0x00800080) != (FPW) 0x00800080) {
836                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
837                         *dest = (FPW) 0x00B000B0;       /* Suspend program      */
838                         res = 1;
839                 }
840         }
841
842         if (res == 0 && (*dest & (FPW) 0x00100010))
843                 res = 1;        /* write failed, time out error is close enough */
844
845         *dest = (FPW) 0x00500050;       /* clear status register        */
846         *dest = (FPW) 0x00FF00FF;       /* make sure in read mode       */
847
848         return (res);
849 }
850
851 #ifdef CFG_FLASH_PROTECTION
852 /*-----------------------------------------------------------------------
853  */
854 int
855 flash_real_protect(flash_info_t * info, long sector, int prot)
856 {
857         int rcode = 0;          /* assume success */
858         FPWV *addr;             /* address of sector */
859         FPW value;
860
861         addr = (FPWV *) (info->start[sector]);
862
863         switch (info->flash_id & FLASH_TYPEMASK) {
864         case FLASH_28F800C3B:
865         case FLASH_28F800C3T:
866         case FLASH_28F160C3B:
867         case FLASH_28F160C3T:
868         case FLASH_28F320C3B:
869         case FLASH_28F320C3T:
870         case FLASH_28F640C3B:
871         case FLASH_28F640C3T:
872                 flash_reset(info);      /* make sure in read mode */
873                 *addr = (FPW) 0x00600060L;      /* lock command setup */
874                 if (prot)
875                         *addr = (FPW) 0x00010001L;      /* lock sector */
876                 else
877                         *addr = (FPW) 0x00D000D0L;      /* unlock sector */
878                 flash_reset(info);      /* reset to read mode */
879
880                 /* now see if it really is locked/unlocked as requested */
881                 *addr = (FPW) 0x00900090;
882                 /* read sector protection at sector address, (A7 .. A0) = 0x02.
883                  * D0 = 1 for each device if protected.
884                  * If at least one device is protected the sector is marked
885                  * protected, but return failure. Mixed protected and
886                  * unprotected devices within a sector should never happen.
887                  */
888                 value = addr[2] & (FPW) 0x00010001;
889                 if (value == 0)
890                         info->protect[sector] = 0;
891                 else if (value == (FPW) 0x00010001)
892                         info->protect[sector] = 1;
893                 else {
894                         /* error, mixed protected and unprotected */
895                         rcode = 1;
896                         info->protect[sector] = 1;
897                 }
898                 if (info->protect[sector] != prot)
899                         rcode = 1;      /* failed to protect/unprotect as requested */
900
901                 /* reload all protection bits from hardware for now */
902                 flash_sync_real_protect(info);
903                 break;
904
905         case FLASH_AM640U:
906         default:
907                 /* no hardware protect that we support */
908                 info->protect[sector] = prot;
909                 break;
910         }
911
912         return rcode;
913 }
914 #endif