de2cca863a9923c5f1492d59250fa5016ffce285
[platform/kernel/u-boot.git] / board / freescale / m54455evb / flash.c
1 /*
2  * (C) Copyright 2000-2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
6  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28
29 #include <asm/immap.h>
30
31 #ifndef CFG_FLASH_CFI
32 typedef unsigned char FLASH_PORT_WIDTH;
33 typedef volatile unsigned char FLASH_PORT_WIDTHV;
34
35 #define FPW             FLASH_PORT_WIDTH
36 #define FPWV            FLASH_PORT_WIDTHV
37
38 #define CFG_FLASH_CFI_WIDTH     FLASH_CFI_8BIT
39 #define CFG_FLASH_NONCFI_WIDTH  FLASH_CFI_8BIT
40
41 /* Intel-compatible flash commands */
42 #define INTEL_PROGRAM   0x00100010
43 #define INTEL_ERASE     0x00200020
44 #define INTEL_WRSETUP   0x00400040
45 #define INTEL_CLEAR     0x00500050
46 #define INTEL_LOCKBIT   0x00600060
47 #define INTEL_PROTECT   0x00010001
48 #define INTEL_STATUS    0x00700070
49 #define INTEL_READID    0x00900090
50 #define INTEL_CFIQRY    0x00980098
51 #define INTEL_SUSERASE  0x00B000B0
52 #define INTEL_PROTPROG  0x00C000C0
53 #define INTEL_CONFIRM   0x00D000D0
54 #define INTEL_WRBLK     0x00e800e8
55 #define INTEL_RESET     0x00FF00FF
56
57 /* Intel-compatible flash status bits */
58 #define INTEL_FINISHED  0x00800080
59 #define INTEL_OK        0x00800080
60 #define INTEL_ERASESUS  0x00600060
61 #define INTEL_WSM_SUS   (INTEL_FINISHED | INTEL_ERASESUS)
62
63 /* 28F160C3B CFI Data offset - This could vary */
64 #define INTEL_CFI_MFG   0x00    /* Manufacturer ID */
65 #define INTEL_CFI_PART  0x01    /* Product ID */
66 #define INTEL_CFI_LOCK  0x02    /* */
67 #define INTEL_CFI_TWPRG 0x1F    /* Typical Single Word Program Timeout 2^n us */
68 #define INTEL_CFI_MBUFW 0x20    /* Typical Max Buffer Write Timeout 2^n us */
69 #define INTEL_CFI_TERB  0x21    /* Typical Block Erase Timeout 2^n ms */
70 #define INTEL_CFI_MWPRG 0x23    /* Maximum Word program timeout 2^n us */
71 #define INTEL_CFI_MERB  0x25    /* Maximum Block Erase Timeout 2^n s */
72 #define INTEL_CFI_SIZE  0x27    /* Device size 2^n bytes */
73 #define INTEL_CFI_CAP   0x28
74 #define INTEL_CFI_WRBUF 0x2A
75 #define INTEL_CFI_BANK  0x2C    /* Number of Bank */
76 #define INTEL_CFI_BLK1A 0x2D    /* Number of Blocks */
77 #define INTEL_CFI_BLK1B 0x2E    /* Number of Blocks */
78 #define INTEL_CFI_SZ1A  0x2F    /* Block Region Size */
79 #define INTEL_CFI_SZ1B  0x30
80 #define INTEL_CFI_BLK2A 0x31
81 #define INTEL_CFI_BLK2B 0x32
82 #define INTEL_CFI_SZ2A  0x33
83 #define INTEL_CFI_SZ2B  0x34
84
85 #define FLASH_CYCLE1    0x0555
86 #define FLASH_CYCLE2    0x0aaa
87
88 #define WR_BLOCK        0x20
89
90 /* not in the flash.h yet */
91 #define FLASH_28F64P30T         0x00B9  /* Intel 28F64P30T   (  64M)            */
92 #define FLASH_28F64P30B         0x00BA  /* Intel 28F64P30B   (  64M)            */
93 #define FLASH_28F128P30T        0x00BB  /* Intel 28F128P30T  ( 128M = 8M x 16 ) */
94 #define FLASH_28F128P30B        0x00BC  /* Intel 28F128P30B  ( 128M = 8M x 16 ) */
95 #define FLASH_28F256P30T        0x00BD  /* Intel 28F256P30T  ( 256M = 16M x 16 )        */
96 #define FLASH_28F256P30B        0x00BE  /* Intel 28F256P30B  ( 256M = 16M x 16 )        */
97
98 #define SYNC                    __asm__("nop")
99
100 /*-----------------------------------------------------------------------
101  * Functions
102  */
103
104 ulong flash_get_size(FPWV * addr, flash_info_t * info);
105 int flash_get_offsets(ulong base, flash_info_t * info);
106 int flash_cmd_rd(volatile u16 * addr, int index);
107 int write_data(flash_info_t * info, ulong dest, FPW data);
108 int write_data_block(flash_info_t * info, ulong src, ulong dest);
109 int write_word_atm(flash_info_t * info, volatile u8 * dest, u16 data);
110 void inline spin_wheel(void);
111 void flash_sync_real_protect(flash_info_t * info);
112 uchar intel_sector_protected(flash_info_t * info, ushort sector);
113
114 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
115
116 ulong flash_init(void)
117 {
118         int i;
119         ulong size = 0;
120         ulong fbase = 0;
121
122         for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
123                 memset(&flash_info[i], 0, sizeof(flash_info_t));
124
125                 switch (i) {
126                 case 0:
127                         fbase = (ulong) CFG_FLASH0_BASE;
128                         break;
129                 case 1:
130                         fbase = (ulong) CFG_FLASH1_BASE;
131                         break;
132                 }
133
134                 flash_get_size((FPWV *) fbase, &flash_info[i]);
135                 flash_get_offsets((ulong) fbase, &flash_info[i]);
136                 fbase += flash_info[i].size;
137                 size += flash_info[i].size;
138
139                 /* get the h/w and s/w protection status in sync */
140                 flash_sync_real_protect(&flash_info[i]);
141         }
142
143         /* Protect monitor and environment sectors */
144         flash_protect(FLAG_PROTECT_SET,
145                       CFG_MONITOR_BASE,
146                       CFG_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
147
148         return size;
149 }
150
151 int flash_get_offsets(ulong base, flash_info_t * info)
152 {
153         int i, j, k;
154         int sectors, bs, banks;
155         ulong start;
156
157         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_ATM) {
158                 int sect[] = CFG_ATMEL_SECT;
159                 int sectsz[] = CFG_ATMEL_SECTSZ;
160
161                 info->start[0] = base;
162                 for (k = 0, i = 0; i < CFG_ATMEL_REGION; i++) {
163                         for (j = 0; j < sect[i]; j++, k++) {
164                                 info->start[k + 1] = info->start[k] + sectsz[i];
165                                 info->protect[k] = 0;
166                         }
167                 }
168         }
169
170         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
171                 volatile u16 *addr16 = (volatile u16 *)base;
172
173                 *addr16 = (FPW) INTEL_RESET;    /* restore read mode */
174                 *addr16 = (FPW) INTEL_READID;
175
176                 banks = addr16[INTEL_CFI_BANK] & 0xff;
177
178                 sectors = 0;
179                 info->start[0] = base;
180
181                 for (k = 0, i = 0; i < banks; i++) {
182                         /* Geometry y1 = y1 + 1, y2 = y2 + 1, CFI spec.
183                          * To be exact, Z = [0x2f 0x30] (LE) * 256 bytes * [0x2D 0x2E] block count
184                          * Z = [0x33 0x34] (LE) * 256 bytes * [0x31 0x32] block count
185                          */
186                         bs = ((((addr16[INTEL_CFI_SZ1B + (i * 4)] & 0xff) << 8)
187                                | (addr16[INTEL_CFI_SZ1A + (i * 4)] & 0xff)) *
188                               0x100);
189                         sectors =
190                             (addr16[INTEL_CFI_BLK1A + (i * 4)] & 0xff) + 1;
191
192                         for (j = 0; j < sectors; j++, k++) {
193                                 info->start[k + 1] = info->start[k] + bs;
194                         }
195                 }
196
197                 *addr16 = (FPW) INTEL_RESET;    /* restore read mode */
198         }
199
200         return ERR_OK;
201 }
202
203 void flash_print_info(flash_info_t * info)
204 {
205         int i;
206
207         switch (info->flash_id & FLASH_VENDMASK) {
208         case FLASH_MAN_INTEL:
209                 printf("INTEL ");
210                 break;
211         case FLASH_MAN_ATM:
212                 printf("ATMEL ");
213                 break;
214         default:
215                 printf("Unknown Vendor ");
216                 break;
217         }
218
219         switch (info->flash_id & FLASH_TYPEMASK) {
220         case FLASH_AT040:
221                 printf("AT49BV040A\n");
222                 break;
223         case FLASH_28F128J3A:
224                 printf("Intel 28F128J3A\n");
225                 break;
226         default:
227                 printf("Unknown Chip Type\n");
228                 return;
229         }
230
231         if (info->size > 0x100000) {
232                 int remainder;
233
234                 printf("  Size: %ld", info->size >> 20);
235
236                 remainder = (info->size % 0x100000);
237                 if (remainder) {
238                         remainder >>= 10;
239                         remainder = (int)((float)
240                                           (((float)remainder / (float)1024) *
241                                            10000));
242                         printf(".%d ", remainder);
243                 }
244
245                 printf("MB in %d Sectors\n", info->sector_count);
246         } else
247                 printf("  Size: %ld KB in %d Sectors\n",
248                        info->size >> 10, info->sector_count);
249
250         printf("  Sector Start Addresses:");
251         for (i = 0; i < info->sector_count; ++i) {
252                 if ((i % 5) == 0)
253                         printf("\n   ");
254                 printf(" %08lX%s",
255                        info->start[i], info->protect[i] ? " (RO)" : "     ");
256         }
257         printf("\n");
258 }
259
260 /*
261  * The following code cannot be run from FLASH!
262  */
263 ulong flash_get_size(FPWV * addr, flash_info_t * info)
264 {
265         volatile u16 *addr16 = (volatile u16 *)addr;
266         int intel = 0, banks = 0;
267         u16 value;
268         int i;
269
270         addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA; /* for Atmel, Intel ignores this */
271         addr[FLASH_CYCLE2] = (FPWV) 0x00550055; /* for Atmel, Intel ignores this */
272         addr[FLASH_CYCLE1] = (FPWV) 0x00900090; /* selects Intel or Atmel */
273
274         switch (addr[0] & 0xff) {
275         case (u8) ATM_MANUFACT:
276                 info->flash_id = FLASH_MAN_ATM;
277                 value = addr[1];
278                 break;
279         case (u8) INTEL_MANUFACT:
280                 /* Terminate Atmel ID read */
281                 addr[0] = (FPWV) 0x00F000F0;
282                 /* Write auto select command: read Manufacturer ID */
283                 /* Write auto select command sequence and test FLASH answer */
284                 *addr16 = (FPW) INTEL_RESET;    /* restore read mode */
285                 *addr16 = (FPW) INTEL_READID;
286
287                 info->flash_id = FLASH_MAN_INTEL;
288                 value = (addr16[INTEL_CFI_MFG] << 8);
289                 value |= addr16[INTEL_CFI_PART] & 0xff;
290                 intel = 1;
291                 break;
292         default:
293                 printf("Unknown Flash\n");
294                 info->flash_id = FLASH_UNKNOWN;
295                 info->sector_count = 0;
296                 info->size = 0;
297
298                 *addr = (FPW) 0x00F000F0;
299                 *addr = (FPW) INTEL_RESET;      /* restore read mode */
300                 return (0);     /* no or unknown flash  */
301         }
302
303         switch (value) {
304         case (u8) ATM_ID_LV040:
305                 info->flash_id += FLASH_AT040;
306                 break;
307         case (u16) INTEL_ID_28F128J3:
308                 info->flash_id += FLASH_28F128J3A;
309                 break;
310         case (u16) INTEL_ID_28F64P30T:
311                 info->flash_id += FLASH_28F64P30T;
312                 break;
313         case (u16) INTEL_ID_28F64P30B:
314                 info->flash_id += FLASH_28F64P30B;
315                 break;
316         case (u16) INTEL_ID_28F128P30T:
317                 info->flash_id += FLASH_28F128P30T;
318                 break;
319         case (u16) INTEL_ID_28F128P30B:
320                 info->flash_id += FLASH_28F128P30B;
321                 break;
322         case (u16) INTEL_ID_28F256P30T:
323                 info->flash_id += FLASH_28F256P30T;
324                 break;
325         case (u16) INTEL_ID_28F256P30B:
326                 info->flash_id += FLASH_28F256P30B;
327                 break;
328         default:
329                 info->flash_id = FLASH_UNKNOWN;
330                 break;
331         }
332
333         if (intel) {
334                 /* Intel spec. under CFI section */
335                 u32 sz;
336                 int sectors, bs;
337
338                 banks = addr16[INTEL_CFI_BANK] & 0xff;
339
340                 sectors = sz = 0;
341                 for (i = 0; i < banks; i++) {
342                         /* Geometry y1 = y1 + 1, y2 = y2 + 1, CFI spec.
343                          * To be exact, Z = [0x2f 0x30] (LE) * 256 bytes * [0x2D 0x2E] block count
344                          * Z = [0x33 0x34] (LE) * 256 bytes * [0x31 0x32] block count
345                          */
346                         bs = ((((addr16[INTEL_CFI_SZ1B + (i * 4)] & 0xff) << 8)
347                                | (addr16[INTEL_CFI_SZ1A + (i * 4)] & 0xff)) *
348                               0x100);
349                         sectors +=
350                             (addr16[INTEL_CFI_BLK1A + (i * 4)] & 0xff) + 1;
351                         sz += (bs * sectors);
352                 }
353
354                 info->sector_count = sectors;
355                 info->size = sz;
356                 *addr = (FPW) INTEL_RESET;      /* restore read mode */
357         } else {
358                 int sect[] = CFG_ATMEL_SECT;
359                 int sectsz[] = CFG_ATMEL_SECTSZ;
360
361                 info->sector_count = 0;
362                 info->size = 0;
363                 for (i = 0; i < CFG_ATMEL_REGION; i++) {
364                         info->sector_count += sect[i];
365                         info->size += sect[i] * sectsz[i];
366                 }
367
368                 /* reset ID mode */
369                 addr[0] = (FPWV) 0x00F000F0;
370         }
371
372         if (info->sector_count > CFG_MAX_FLASH_SECT) {
373                 printf("** ERROR: sector count %d > max (%d) **\n",
374                        info->sector_count, CFG_MAX_FLASH_SECT);
375                 info->sector_count = CFG_MAX_FLASH_SECT;
376         }
377
378         return (info->size);
379 }
380
381 int flash_cmd_rd(volatile u16 * addr, int index)
382 {
383         return (int)addr[index];
384 }
385
386 /*
387  * This function gets the u-boot flash sector protection status
388  * (flash_info_t.protect[]) in sync with the sector protection
389  * status stored in hardware.
390  */
391 void flash_sync_real_protect(flash_info_t * info)
392 {
393         int i;
394
395         switch (info->flash_id & FLASH_TYPEMASK) {
396         case FLASH_28F160C3B:
397         case FLASH_28F160C3T:
398         case FLASH_28F320C3B:
399         case FLASH_28F320C3T:
400         case FLASH_28F640C3B:
401         case FLASH_28F640C3T:
402                 for (i = 0; i < info->sector_count; ++i) {
403                         info->protect[i] = intel_sector_protected(info, i);
404                 }
405                 break;
406         default:
407                 /* no h/w protect support */
408                 break;
409         }
410 }
411
412 /*
413  * checks if "sector" in bank "info" is protected. Should work on intel
414  * strata flash chips 28FxxxJ3x in 8-bit mode.
415  * Returns 1 if sector is protected (or timed-out while trying to read
416  * protection status), 0 if it is not.
417  */
418 uchar intel_sector_protected(flash_info_t * info, ushort sector)
419 {
420         FPWV *addr;
421         FPWV *lock_conf_addr;
422         ulong start;
423         unsigned char ret;
424
425         /*
426          * first, wait for the WSM to be finished. The rationale for
427          * waiting for the WSM to become idle for at most
428          * CFG_FLASH_ERASE_TOUT is as follows. The WSM can be busy
429          * because of: (1) erase, (2) program or (3) lock bit
430          * configuration. So we just wait for the longest timeout of
431          * the (1)-(3), i.e. the erase timeout.
432          */
433
434         /* wait at least 35ns (W12) before issuing Read Status Register */
435         /*udelay(1); */
436         addr = (FPWV *) info->start[sector];
437         *addr = (FPW) INTEL_STATUS;
438
439         start = get_timer(0);
440         while ((*addr & (FPW) INTEL_FINISHED) != (FPW) INTEL_FINISHED) {
441                 if (get_timer(start) > CFG_FLASH_UNLOCK_TOUT) {
442                         *addr = (FPW) INTEL_RESET;      /* restore read mode */
443                         printf("WSM busy too long, can't get prot status\n");
444                         return 1;
445                 }
446         }
447
448         /* issue the Read Identifier Codes command */
449         *addr = (FPW) INTEL_READID;
450
451         /* Intel example code uses offset of 4 for 8-bit flash */
452         lock_conf_addr = (FPWV *) info->start[sector];
453         ret = (lock_conf_addr[INTEL_CFI_LOCK] & (FPW) INTEL_PROTECT) ? 1 : 0;
454
455         /* put flash back in read mode */
456         *addr = (FPW) INTEL_RESET;
457
458         return ret;
459 }
460
461 int flash_erase(flash_info_t * info, int s_first, int s_last)
462 {
463         int flag, prot, sect;
464         ulong type, start, last;
465         int rcode = 0, intel = 0;
466
467         if ((s_first < 0) || (s_first > s_last)) {
468                 if (info->flash_id == FLASH_UNKNOWN)
469                         printf("- missing\n");
470                 else
471                         printf("- no sectors to erase\n");
472                 return 1;
473         }
474
475         type = (info->flash_id & FLASH_VENDMASK);
476
477         if (type != (FLASH_MAN_INTEL & FLASH_VENDMASK)) {
478                 if (type != (FLASH_MAN_ATM & FLASH_VENDMASK)) {
479                         type = (info->flash_id & FLASH_VENDMASK);
480                         printf
481                             ("Can't erase unknown flash type %08lx - aborted\n",
482                              info->flash_id);
483                         return 1;
484                 }
485         }
486
487         if (type == FLASH_MAN_INTEL)
488                 intel = 1;
489
490         prot = 0;
491         for (sect = s_first; sect <= s_last; ++sect) {
492                 if (info->protect[sect]) {
493                         prot++;
494                 }
495         }
496
497         if (prot)
498                 printf("- Warning: %d protected sectors will not be erased!\n",
499                        prot);
500         else
501                 printf("\n");
502
503         start = get_timer(0);
504         last = start;
505
506         /* Start erase on unprotected sectors */
507         for (sect = s_first; sect <= s_last; sect++) {
508                 if (info->protect[sect] == 0) { /* not protected */
509
510                         FPWV *addr = (FPWV *) (info->start[sect]);
511                         int min = 0;
512
513                         printf(".");
514
515                         /* arm simple, non interrupt dependent timer */
516                         start = get_timer(0);
517
518                         if (intel) {
519                                 *addr = (FPW) INTEL_READID;
520                                 min = addr[INTEL_CFI_TERB] & 0xff;
521                                 min = 1 << min; /* ms */
522                                 min = (min / info->sector_count) * 1000;
523
524                                 /* start erase block */
525                                 *addr = (FPW) INTEL_CLEAR;      /* clear status register */
526                                 *addr = (FPW) INTEL_ERASE;      /* erase setup */
527                                 *addr = (FPW) INTEL_CONFIRM;    /* erase confirm */
528
529                                 while ((*addr & (FPW) INTEL_FINISHED) !=
530                                        (FPW) INTEL_FINISHED) {
531
532                                         if (get_timer(start) >
533                                             CFG_FLASH_ERASE_TOUT) {
534                                                 printf("Timeout\n");
535                                                 *addr = (FPW) INTEL_SUSERASE;   /* suspend erase     */
536                                                 *addr = (FPW) INTEL_RESET;      /* reset to read mode */
537
538                                                 rcode = 1;
539                                                 break;
540                                         }
541                                 }
542
543                                 *addr = (FPW) INTEL_RESET;      /* resest to read mode          */
544                         } else {
545                                 FPWV *base;     /* first address in bank */
546                                 FPWV *atmeladdr;
547
548                                 flag = disable_interrupts();
549
550                                 atmeladdr = (FPWV *) addr;      /* concatenate to 8 bit */
551                                 base = (FPWV *) (CFG_ATMEL_BASE);       /* First sector */
552
553                                 base[FLASH_CYCLE1] = (u8) 0x00AA00AA;   /* unlock */
554                                 base[FLASH_CYCLE2] = (u8) 0x00550055;   /* unlock */
555                                 base[FLASH_CYCLE1] = (u8) 0x00800080;   /* erase mode */
556                                 base[FLASH_CYCLE1] = (u8) 0x00AA00AA;   /* unlock */
557                                 base[FLASH_CYCLE2] = (u8) 0x00550055;   /* unlock */
558                                 *atmeladdr = (u8) 0x00300030;   /* erase sector */
559
560                                 if (flag)
561                                         enable_interrupts();
562
563                                 while ((*atmeladdr & (u8) 0x00800080) !=
564                                        (u8) 0x00800080) {
565                                         if (get_timer(start) >
566                                             CFG_FLASH_ERASE_TOUT) {
567                                                 printf("Timeout\n");
568                                                 *atmeladdr = (u8) 0x00F000F0;   /* reset to read mode */
569
570                                                 rcode = 1;
571                                                 break;
572                                         }
573                                 }
574
575                                 *atmeladdr = (u8) 0x00F000F0;   /* reset to read mode */
576                         }       /* Atmel or Intel */
577                 }
578         }
579         printf(" done\n");
580
581         return rcode;
582 }
583
584 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
585 {
586         if (info->flash_id == FLASH_UNKNOWN)
587                 return 4;
588
589         switch (info->flash_id & FLASH_VENDMASK) {
590         case FLASH_MAN_ATM:
591                 {
592                         u16 data = 0;
593                         int bytes;      /* number of bytes to program in current word */
594                         int left;       /* number of bytes left to program */
595                         int i, res;
596
597                         for (left = cnt, res = 0;
598                              left > 0 && res == 0;
599                              addr += sizeof(data), left -=
600                              sizeof(data) - bytes) {
601
602                                 bytes = addr & (sizeof(data) - 1);
603                                 addr &= ~(sizeof(data) - 1);
604
605                                 /* combine source and destination data so can program
606                                  * an entire word of 16 or 32 bits
607                                  */
608                                 for (i = 0; i < sizeof(data); i++) {
609                                         data <<= 8;
610                                         if (i < bytes || i - bytes >= left)
611                                                 data += *((uchar *) addr + i);
612                                         else
613                                                 data += *src++;
614                                 }
615
616                                 data = (data >> 8) | (data << 8);
617                                 res = write_word_atm(info, (FPWV *) addr, data);
618                         }
619                         return res;
620                 }               /* case FLASH_MAN_ATM */
621
622         case FLASH_MAN_INTEL:
623                 {
624                         ulong cp, wp;
625                         u16 data;
626                         int count, i, l, rc, port_width;
627
628                         /* get lower word aligned address */
629                         wp = addr;
630                         port_width = sizeof(FPW);
631
632                         /*
633                          * handle unaligned start bytes
634                          */
635                         if ((l = addr - wp) != 0) {
636                                 data = 0;
637                                 for (i = 0, cp = wp; i < l; ++i, ++cp) {
638                                         data = (data << 8) | (*(uchar *) cp);
639                                 }
640
641                                 for (; i < port_width && cnt > 0; ++i) {
642                                         data = (data << 8) | *src++;
643                                         --cnt;
644                                         ++cp;
645                                 }
646
647                                 for (; cnt == 0 && i < port_width; ++i, ++cp)
648                                         data = (data << 8) | (*(uchar *) cp);
649
650                                 if ((rc = write_data(info, wp, data)) != 0)
651                                         return (rc);
652
653                                 wp += port_width;
654                         }
655
656                         if (cnt > WR_BLOCK) {
657                                 /*
658                                  * handle word aligned part
659                                  */
660                                 count = 0;
661                                 while (cnt >= WR_BLOCK) {
662
663                                         if ((rc =
664                                              write_data_block(info,
665                                                               (ulong) src,
666                                                               wp)) != 0)
667                                                 return (rc);
668
669                                         wp += WR_BLOCK;
670                                         src += WR_BLOCK;
671                                         cnt -= WR_BLOCK;
672
673                                         if (count++ > 0x800) {
674                                                 spin_wheel();
675                                                 count = 0;
676                                         }
677                                 }
678                         }
679
680                         /* handle word aligned part */
681                         if (cnt < WR_BLOCK) {
682                                 /*
683                                  * handle word aligned part
684                                  */
685                                 count = 0;
686                                 while (cnt >= port_width) {
687                                         data = 0;
688                                         for (i = 0; i < port_width; ++i)
689                                                 data = (data << 8) | *src++;
690
691                                         if ((rc =
692                                              write_data(info,
693                                                         (ulong) ((FPWV *) wp),
694                                                         (FPW) (data))) != 0)
695                                                 return (rc);
696
697                                         wp += port_width;
698                                         cnt -= port_width;
699                                         if (count++ > 0x800) {
700                                                 spin_wheel();
701                                                 count = 0;
702                                         }
703                                 }
704                         }
705
706                         if (cnt == 0)
707                                 return ERR_OK;
708
709                         /*
710                          * handle unaligned tail bytes
711                          */
712                         data = 0;
713                         for (i = 0, cp = wp; i < port_width && cnt > 0;
714                              ++i, ++cp) {
715                                 data = (data << 8) | (*src++);
716                                 --cnt;
717                         }
718                         for (; i < port_width; ++i, ++cp) {
719                                 data = (data << 8) | (*(uchar *) cp);
720                         }
721
722                         return write_data(info, (ulong) ((FPWV *) wp),
723                                           (FPW) data);
724
725                 }               /* case FLASH_MAN_INTEL */
726
727         }                       /* switch */
728
729         return ERR_OK;
730 }
731
732 /*-----------------------------------------------------------------------
733  * Write a word or halfword to Flash, returns:
734  * 0 - OK
735  * 1 - write timeout
736  * 2 - Flash not erased
737  */
738 int write_data_block(flash_info_t * info, ulong src, ulong dest)
739 {
740         FPWV *srcaddr = (FPWV *) src;
741         FPWV *dstaddr = (FPWV *) dest;
742         ulong start;
743         int flag, i;
744
745         /* Check if Flash is (sufficiently) erased */
746         for (i = 0; i < WR_BLOCK; i++)
747                 if ((*dstaddr++ & 0xff) != 0xff) {
748                         printf("not erased at %08lx (%lx)\n",
749                                (ulong) dstaddr, *dstaddr);
750                         return (2);
751                 }
752
753         dstaddr = (FPWV *) dest;
754
755         /* Disable interrupts which might cause a timeout here */
756         flag = disable_interrupts();
757
758         *dstaddr = (FPW) INTEL_WRBLK;   /* write block setup */
759
760         if (flag)
761                 enable_interrupts();
762
763         /* arm simple, non interrupt dependent timer */
764         start = get_timer(0);
765
766         /* wait while polling the status register */
767         while ((*dstaddr & (FPW) INTEL_FINISHED) != (FPW) INTEL_OK) {
768                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
769                         *dstaddr = (FPW) INTEL_RESET;   /* restore read mode */
770                         return (1);
771                 }
772         }
773
774         *dstaddr = (FPW) WR_BLOCK - 1;  /* write 32 to buffer */
775         for (i = 0; i < WR_BLOCK; i++)
776                 *dstaddr++ = *srcaddr++;
777
778         dstaddr -= 1;
779         *dstaddr = (FPW) INTEL_CONFIRM; /* write 32 to buffer */
780
781         /* arm simple, non interrupt dependent timer */
782         start = get_timer(0);
783
784         /* wait while polling the status register */
785         while ((*dstaddr & (FPW) INTEL_FINISHED) != (FPW) INTEL_OK) {
786                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
787                         *dstaddr = (FPW) INTEL_RESET;   /* restore read mode */
788                         return (1);
789                 }
790         }
791
792         *dstaddr = (FPW) INTEL_RESET;   /* restore read mode */
793
794         return (0);
795 }
796
797 /*-----------------------------------------------------------------------
798  * Write a word or halfword to Flash, returns:
799  * 0 - OK
800  * 1 - write timeout
801  * 2 - Flash not erased
802  */
803 int write_data(flash_info_t * info, ulong dest, FPW data)
804 {
805         FPWV *addr = (FPWV *) dest;
806         ulong start;
807         int flag;
808
809         /* Check if Flash is (sufficiently) erased */
810         if ((*addr & data) != data) {
811                 printf("not erased at %08lx (%lx)\n", (ulong) addr,
812                        (ulong) * addr);
813                 return (2);
814         }
815
816         /* Disable interrupts which might cause a timeout here */
817         flag = (int)disable_interrupts();
818
819         *addr = (FPW) INTEL_CLEAR;
820         *addr = (FPW) INTEL_RESET;
821
822         *addr = (FPW) INTEL_WRSETUP;    /* write setup */
823         *addr = data;
824
825         if (flag)
826                 enable_interrupts();
827
828         /* arm simple, non interrupt dependent timer */
829         start = get_timer(0);
830
831         /* wait while polling the status register */
832         while ((*addr & (FPW) INTEL_OK) != (FPW) INTEL_OK) {
833                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
834                         *addr = (FPW) INTEL_SUSERASE;   /* suspend mode */
835                         *addr = (FPW) INTEL_CLEAR;      /* clear status */
836                         *addr = (FPW) INTEL_RESET;      /* reset */
837                         return (1);
838                 }
839         }
840
841         *addr = (FPW) INTEL_CLEAR;      /* clear status */
842         *addr = (FPW) INTEL_RESET;      /* restore read mode */
843
844         return (0);
845 }
846
847 /*-----------------------------------------------------------------------
848  * Write a word to Flash for ATMEL FLASH
849  * A word is 16 bits, whichever the bus width of the flash bank
850  * (not an individual chip) is.
851  *
852  * returns:
853  * 0 - OK
854  * 1 - write timeout
855  * 2 - Flash not erased
856  */
857 int write_word_atm(flash_info_t * info, volatile u8 * dest, u16 data)
858 {
859         ulong start;
860         int flag, i;
861         int res = 0;            /* result, assume success */
862         FPWV *base;             /* first address in flash bank */
863
864         /* Check if Flash is (sufficiently) erased */
865         if ((*((volatile u16 *)dest) & data) != data) {
866                 return (2);
867         }
868
869         base = (FPWV *) (CFG_ATMEL_BASE);
870
871         for (i = 0; i < sizeof(u16); i++) {
872                 /* Disable interrupts which might cause a timeout here */
873                 flag = disable_interrupts();
874
875                 base[FLASH_CYCLE1] = (u8) 0x00AA00AA;   /* unlock */
876                 base[FLASH_CYCLE2] = (u8) 0x00550055;   /* unlock */
877                 base[FLASH_CYCLE1] = (u8) 0x00A000A0;   /* selects program mode */
878
879                 *dest = data;   /* start programming the data */
880
881                 /* re-enable interrupts if necessary */
882                 if (flag)
883                         enable_interrupts();
884
885                 start = get_timer(0);
886
887                 /* data polling for D7 */
888                 while (res == 0
889                        && (*dest & (u8) 0x00800080) !=
890                        (data & (u8) 0x00800080)) {
891                         if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
892                                 *dest = (u8) 0x00F000F0;        /* reset bank */
893                                 res = 1;
894                         }
895                 }
896
897                 *dest++ = (u8) 0x00F000F0;      /* reset bank */
898                 data >>= 8;
899         }
900
901         return (res);
902 }
903
904 void inline spin_wheel(void)
905 {
906         static int p = 0;
907         static char w[] = "\\/-";
908
909         printf("\010%c", w[p]);
910         (++p == 3) ? (p = 0) : 0;
911 }
912
913 #ifdef CFG_FLASH_PROTECTION
914 /*-----------------------------------------------------------------------
915  */
916 int flash_real_protect(flash_info_t * info, long sector, int prot)
917 {
918         int rcode = 0;          /* assume success */
919         FPWV *addr;             /* address of sector */
920         FPW value;
921
922         addr = (FPWV *) (info->start[sector]);
923
924         switch (info->flash_id & FLASH_TYPEMASK) {
925         case FLASH_28F160C3B:
926         case FLASH_28F160C3T:
927         case FLASH_28F320C3B:
928         case FLASH_28F320C3T:
929         case FLASH_28F640C3B:
930         case FLASH_28F640C3T:
931                 *addr = (FPW) INTEL_RESET;      /* make sure in read mode */
932                 *addr = (FPW) INTEL_LOCKBIT;    /* lock command setup */
933
934                 if (prot)
935                         *addr = (FPW) INTEL_PROTECT;    /* lock sector */
936                 else
937                         *addr = (FPW) INTEL_CONFIRM;    /* unlock sector */
938
939                 /* now see if it really is locked/unlocked as requested */
940                 *addr = (FPW) INTEL_READID;
941
942                 /* read sector protection at sector address, (A7 .. A0) = 0x02.
943                  * D0 = 1 for each device if protected.
944                  * If at least one device is protected the sector is marked
945                  * protected, but return failure. Mixed protected and
946                  * unprotected devices within a sector should never happen.
947                  */
948                 value = addr[2] & (FPW) INTEL_PROTECT;
949                 if (value == 0)
950                         info->protect[sector] = 0;
951                 else if (value == (FPW) INTEL_PROTECT)
952                         info->protect[sector] = 1;
953                 else {
954                         /* error, mixed protected and unprotected */
955                         rcode = 1;
956                         info->protect[sector] = 1;
957                 }
958                 if (info->protect[sector] != prot)
959                         rcode = 1;      /* failed to protect/unprotect as requested */
960
961                 /* reload all protection bits from hardware for now */
962                 flash_sync_real_protect(info);
963                 break;
964
965         default:
966                 /* no hardware protect that we support */
967                 info->protect[sector] = prot;
968                 break;
969         }
970
971         return rcode;
972 }
973 #endif
974 #endif