* Patches by Reinhard Meyer, 14 Feb 2004:
[platform/kernel/u-boot.git] / board / emk / common / flash.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * (C) Copyright 2003
6  * Reinhard Meyer, EMK Elektronik GmbH, r.meyer@emk-elektronik.de
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 flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
30
31 #if defined (CONFIG_TOP860)
32   typedef unsigned short FLASH_PORT_WIDTH;
33   typedef volatile unsigned short FLASH_PORT_WIDTHV;
34   #define       FLASH_ID_MASK   0xFF
35
36   #define FPW   FLASH_PORT_WIDTH
37   #define FPWV  FLASH_PORT_WIDTHV
38
39   #define FLASH_CYCLE1  0x0555
40   #define FLASH_CYCLE2  0x02aa
41   #define FLASH_ID1             0
42   #define FLASH_ID2             1
43 #endif
44
45 #if defined (CONFIG_TOP5200)
46   typedef unsigned char FLASH_PORT_WIDTH;
47   typedef volatile unsigned char FLASH_PORT_WIDTHV;
48   #define       FLASH_ID_MASK   0xFF
49
50   #define FPW   FLASH_PORT_WIDTH
51   #define FPWV  FLASH_PORT_WIDTHV
52
53   #define FLASH_CYCLE1  0x0aaa
54   #define FLASH_CYCLE2  0x0555
55   #define FLASH_ID1             0
56   #define FLASH_ID2             2
57 #endif
58
59 /*-----------------------------------------------------------------------
60  * Functions
61  */
62 static ulong flash_get_size(FPWV *addr, flash_info_t *info);
63 static void flash_reset(flash_info_t *info);
64 static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
65 static flash_info_t *flash_get_info(ulong base);
66
67 /*-----------------------------------------------------------------------
68  * flash_init()
69  *
70  * sets up flash_info and returns size of FLASH (bytes)
71  */
72 unsigned long flash_init (void)
73 {
74         unsigned long size = 0;
75         int i = 0;
76         extern void flash_preinit(void);
77         extern void flash_afterinit(uint, ulong, ulong);
78         ulong flashbase = CFG_FLASH_BASE;
79
80         flash_preinit();
81
82         /* There is only ONE FLASH device */
83         memset(&flash_info[i], 0, sizeof(flash_info_t));
84         flash_info[i].size =
85                         flash_get_size((FPW *)flashbase, &flash_info[i]);
86         size += flash_info[i].size;
87
88 #if CFG_MONITOR_BASE >= CFG_FLASH_BASE
89         /* monitor protection ON by default */
90         flash_protect(FLAG_PROTECT_SET,
91                       CFG_MONITOR_BASE,
92                       CFG_MONITOR_BASE+monitor_flash_len-1,
93                       flash_get_info(CFG_MONITOR_BASE));
94 #endif
95
96 #ifdef  CFG_ENV_IS_IN_FLASH
97         /* ENV protection ON by default */
98         flash_protect(FLAG_PROTECT_SET,
99                       CFG_ENV_ADDR,
100                       CFG_ENV_ADDR+CFG_ENV_SIZE-1,
101                       flash_get_info(CFG_ENV_ADDR));
102 #endif
103
104
105         flash_afterinit(i, flash_info[i].start[0], flash_info[i].size);
106         return size ? size : 1;
107 }
108
109 /*-----------------------------------------------------------------------
110  */
111 static void flash_reset(flash_info_t *info)
112 {
113         FPWV *base = (FPWV *)(info->start[0]);
114
115         /* Put FLASH back in read mode */
116         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
117                 *base = (FPW)0x00FF00FF;        /* Intel Read Mode */
118         else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
119                 *base = (FPW)0x00F000F0;        /* AMD Read Mode */
120 }
121
122 /*-----------------------------------------------------------------------
123  */
124
125 static flash_info_t *flash_get_info(ulong base)
126 {
127         int i;
128         flash_info_t * info;
129
130         for (i = 0; i < CFG_MAX_FLASH_BANKS; i ++) {
131                 info = & flash_info[i];
132                 if (info->size &&
133                         info->start[0] <= base && base <= info->start[0] + info->size - 1)
134                         break;
135         }
136
137         return i == CFG_MAX_FLASH_BANKS ? 0 : info;
138 }
139
140 /*-----------------------------------------------------------------------
141  */
142
143 void flash_print_info (flash_info_t *info)
144 {
145         int i;
146         uchar *boottype;
147         uchar *bootletter;
148         uchar *fmt;
149         uchar botbootletter[] = "B";
150         uchar topbootletter[] = "T";
151         uchar botboottype[] = "bottom boot sector";
152         uchar topboottype[] = "top boot sector";
153
154         if (info->flash_id == FLASH_UNKNOWN) {
155                 printf ("missing or unknown FLASH type\n");
156                 return;
157         }
158
159         switch (info->flash_id & FLASH_VENDMASK) {
160         case FLASH_MAN_AMD:     printf ("AMD ");                break;
161 #if 0
162         case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
163         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
164         case FLASH_MAN_SST:     printf ("SST ");                break;
165         case FLASH_MAN_STM:     printf ("STM ");                break;
166         case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
167 #endif
168         default:                printf ("Unknown Vendor ");     break;
169         }
170
171         /* check for top or bottom boot, if it applies */
172         if (info->flash_id & FLASH_BTYPE) {
173                 boottype = botboottype;
174                 bootletter = botbootletter;
175         }
176         else {
177                 boottype = topboottype;
178                 bootletter = topbootletter;
179         }
180
181         switch (info->flash_id & FLASH_TYPEMASK) {
182         case FLASH_AM160T:
183         case FLASH_AM160B:
184                 fmt = "29LV160%s (16 Mbit, %s)\n";
185                 break;
186         default:
187                 fmt = "Unknown Chip Type\n";
188                 break;
189         }
190
191         printf (fmt, bootletter, boottype);
192
193         printf ("  Size: %ld MB in %d Sectors\n",
194                 info->size >> 20,
195                 info->sector_count);
196
197         printf ("  Sector Start Addresses:");
198
199         for (i=0; i<info->sector_count; ++i) {
200                 ulong   size;
201                 int             erased;
202                 ulong   *flash = (unsigned long *) info->start[i];
203
204                 if ((i % 5) == 0) {
205                         printf ("\n   ");
206                 }
207
208                 /*
209                  * Check if whole sector is erased
210                  */
211                 size =
212                         (i != (info->sector_count - 1)) ?
213                         (info->start[i + 1] - info->start[i]) >> 2 :
214                 (info->start[0] + info->size - info->start[i]) >> 2;
215
216                 for (
217                         flash = (unsigned long *) info->start[i], erased = 1;
218                                 (flash != (unsigned long *) info->start[i] + size) && erased;
219                                         flash++
220                         )
221                         erased = *flash == ~0x0UL;
222
223                 printf (" %08lX %s %s",
224                         info->start[i],
225                         erased ? "E": " ",
226                         info->protect[i] ? "(RO)" : "    ");
227         }
228
229         printf ("\n");
230 }
231
232 /*-----------------------------------------------------------------------
233  */
234
235 /*
236  * The following code cannot be run from FLASH!
237  */
238
239 ulong flash_get_size (FPWV *addr, flash_info_t *info)
240 {
241         int             i;
242         ulong   offset;
243
244         /* Write auto select command: read Manufacturer ID */
245         /* Write auto select command sequence and test FLASH answer */
246         addr[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* for AMD, Intel ignores this */
247         addr[FLASH_CYCLE2] = (FPW)0x00550055;   /* for AMD, Intel ignores this */
248         addr[FLASH_CYCLE1] = (FPW)0x00900090;   /* selects Intel or AMD */
249
250         /* The manufacturer codes are only 1 byte, so just use 1 byte.
251          * This works for any bus width and any FLASH device width.
252          */
253         udelay(100);
254         switch (addr[FLASH_ID1] & 0xff) {
255
256         case (uchar)AMD_MANUFACT:
257                 info->flash_id = FLASH_MAN_AMD;
258                 break;
259
260 #if 0
261         case (uchar)INTEL_MANUFACT:
262                 info->flash_id = FLASH_MAN_INTEL;
263                 break;
264 #endif
265
266         default:
267                 printf ("unknown vendor=%x ", addr[FLASH_ID1] & 0xff);
268                 info->flash_id = FLASH_UNKNOWN;
269                 info->sector_count = 0;
270                 info->size = 0;
271                 break;
272         }
273
274         /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
275         if (info->flash_id != FLASH_UNKNOWN) switch ((FPW)addr[FLASH_ID2]) {
276
277         case (FPW)AMD_ID_LV160B:
278                 info->flash_id += FLASH_AM160B;
279                 info->sector_count = 35;
280                 info->size = 0x00200000;
281 #ifdef CFG_LOWBOOT
282                 offset = 0;
283 #else
284                 offset = 0x00e00000;
285 #endif
286                 info->start[0] = (ulong)addr + offset;
287                 info->start[1] = (ulong)addr + offset + 0x4000;
288                 info->start[2] = (ulong)addr + offset + 0x6000;
289                 info->start[3] = (ulong)addr + offset + 0x8000;
290                 for (i = 4; i < info->sector_count; i++)
291                 {
292                         info->start[i] = (ulong)addr + offset + 0x10000 * (i-3);
293                 }
294                 break;
295
296         default:
297                 printf ("unknown AMD device=%x ", (FPW)addr[FLASH_ID2]);
298                 info->flash_id = FLASH_UNKNOWN;
299                 info->sector_count = 0;
300                 info->size = 0;
301                 return (0);                     /* => no or unknown flash */
302         }
303
304         /* Put FLASH back in read mode */
305         flash_reset(info);
306
307         return (info->size);
308 }
309
310 /*-----------------------------------------------------------------------
311  */
312
313 int     flash_erase (flash_info_t *info, int s_first, int s_last)
314 {
315         FPWV *addr;
316         int flag, prot, sect;
317         int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
318         ulong start, now, last;
319         int rcode = 0;
320
321         if ((s_first < 0) || (s_first > s_last)) {
322                 if (info->flash_id == FLASH_UNKNOWN) {
323                         printf ("- missing\n");
324                 } else {
325                         printf ("- no sectors to erase\n");
326                 }
327                 return 1;
328         }
329
330         switch (info->flash_id & FLASH_TYPEMASK) {
331         case FLASH_AM160B:
332                 break;
333         case FLASH_UNKNOWN:
334         default:
335                 printf ("Can't erase unknown flash type %08lx - aborted\n",
336                         info->flash_id);
337                 return 1;
338         }
339
340         prot = 0;
341         for (sect=s_first; sect<=s_last; ++sect) {
342                 if (info->protect[sect]) {
343                         prot++;
344                 }
345         }
346
347         if (prot) {
348                 printf ("- Warning: %d protected sectors will not be erased!\n",
349                         prot);
350         } else {
351                 printf ("\n");
352         }
353
354         last  = get_timer(0);
355
356         /* Start erase on unprotected sectors */
357         for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
358
359                 if (info->protect[sect] != 0)   /* protected, skip it */
360                         continue;
361
362                 /* Disable interrupts which might cause a timeout here */
363                 flag = disable_interrupts();
364
365                 addr = (FPWV *)(info->start[sect]);
366                 if (intel) {
367                         *addr = (FPW)0x00500050; /* clear status register */
368                         *addr = (FPW)0x00200020; /* erase setup */
369                         *addr = (FPW)0x00D000D0; /* erase confirm */
370                 }
371                 else {
372                         /* must be AMD style if not Intel */
373                         FPWV *base;             /* first address in bank */
374
375                         base = (FPWV *)(info->start[0]);
376                         base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
377                         base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
378                         base[FLASH_CYCLE1] = (FPW)0x00800080;   /* erase mode */
379                         base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
380                         base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
381                         *addr = (FPW)0x00300030;        /* erase sector */
382                 }
383
384                 /* re-enable interrupts if necessary */
385                 if (flag)
386                         enable_interrupts();
387
388                 start = get_timer(0);
389
390                 /* wait at least 50us for AMD, 80us for Intel.
391                  * Let's wait 1 ms.
392                  */
393                 udelay (1000);
394
395                 while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
396                         if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
397                                 printf ("Timeout\n");
398
399                                 if (intel) {
400                                         /* suspend erase        */
401                                         *addr = (FPW)0x00B000B0;
402                                 }
403
404                                 flash_reset(info);      /* reset to read mode */
405                                 rcode = 1;              /* failed */
406                                 break;
407                         }
408
409                         /* show that we're waiting */
410                         if ((get_timer(last)) > CFG_HZ) {/* every second */
411                                 putc ('.');
412                                 last = get_timer(0);
413                         }
414                 }
415
416                 /* show that we're waiting */
417                 if ((get_timer(last)) > CFG_HZ) {       /* every second */
418                         putc ('.');
419                         last = get_timer(0);
420                 }
421
422                 flash_reset(info);      /* reset to read mode */
423         }
424
425         printf (" done\n");
426         return rcode;
427 }
428
429 /*-----------------------------------------------------------------------
430  * Copy memory to flash, returns:
431  * 0 - OK
432  * 1 - write timeout
433  * 2 - Flash not erased
434  */
435 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
436 {
437         FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
438         int bytes;        /* number of bytes to program in current word         */
439         int left;         /* number of bytes left to program                    */
440         int i, res;
441
442         for (left = cnt, res = 0;
443                  left > 0 && res == 0;
444                  addr += sizeof(data), left -= sizeof(data) - bytes) {
445
446                 bytes = addr & (sizeof(data) - 1);
447                 addr &= ~(sizeof(data) - 1);
448
449                 /* combine source and destination data so can program
450                  * an entire word of 16 or 32 bits
451                  */
452                 for (i = 0; i < sizeof(data); i++) {
453                         data <<= 8;
454                         if (i < bytes || i - bytes >= left )
455                                 data += *((uchar *)addr + i);
456                         else
457                                 data += *src++;
458                 }
459
460                 /* write one word to the flash */
461                 switch (info->flash_id & FLASH_VENDMASK) {
462                 case FLASH_MAN_AMD:
463                         res = write_word_amd(info, (FPWV *)addr, data);
464                         break;
465                 default:
466                         /* unknown flash type, error! */
467                         printf ("missing or unknown FLASH type\n");
468                         res = 1;        /* not really a timeout, but gives error */
469                         break;
470                 }
471         }
472
473         return (res);
474 }
475
476 /*-----------------------------------------------------------------------
477  * Write a word to Flash for AMD FLASH
478  * A word is 16 or 32 bits, whichever the bus width of the flash bank
479  * (not an individual chip) is.
480  *
481  * returns:
482  * 0 - OK
483  * 1 - write timeout
484  * 2 - Flash not erased
485  */
486 static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
487 {
488         ulong start;
489         int flag;
490         int res = 0;    /* result, assume success       */
491         FPWV *base;             /* first address in flash bank  */
492
493         /* Check if Flash is (sufficiently) erased */
494         if ((*dest & data) != data) {
495                 return (2);
496         }
497
498
499         base = (FPWV *)(info->start[0]);
500
501         /* Disable interrupts which might cause a timeout here */
502         flag = disable_interrupts();
503
504         base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
505         base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
506         base[FLASH_CYCLE1] = (FPW)0x00A000A0;   /* selects program mode */
507
508         *dest = data;           /* start programming the data   */
509
510         /* re-enable interrupts if necessary */
511         if (flag)
512                 enable_interrupts();
513
514         start = get_timer (0);
515
516         /* data polling for D7 */
517         while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
518                 if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
519                         *dest = (FPW)0x00F000F0;        /* reset bank */
520                         res = 1;
521                 }
522         }
523
524         return (res);
525 }