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