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