]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/atc/flash.c
sandbox: Add a simple sound driver
[karo-tx-uboot.git] / board / atc / flash.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9
10 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
11
12 /* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
13  *        has nothing to do with the flash chip being 8-bit or 16-bit.
14  */
15 #ifdef CONFIG_FLASH_16BIT
16 typedef unsigned short FLASH_PORT_WIDTH;
17 typedef volatile unsigned short FLASH_PORT_WIDTHV;
18 #define FLASH_ID_MASK   0xFFFF
19 #else
20 typedef unsigned long FLASH_PORT_WIDTH;
21 typedef volatile unsigned long FLASH_PORT_WIDTHV;
22 #define FLASH_ID_MASK   0xFFFFFFFF
23 #endif
24
25 #define FPW     FLASH_PORT_WIDTH
26 #define FPWV    FLASH_PORT_WIDTHV
27
28 #define ORMASK(size) ((-size) & OR_AM_MSK)
29
30 #define FLASH_CYCLE1    0x0555
31 #define FLASH_CYCLE2    0x02aa
32
33 /*-----------------------------------------------------------------------
34  * Functions
35  */
36 static ulong flash_get_size(FPWV *addr, flash_info_t *info);
37 static void flash_reset(flash_info_t *info);
38 static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data);
39 static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
40 static void flash_get_offsets(ulong base, flash_info_t *info);
41 static flash_info_t *flash_get_info(ulong base);
42
43 /*-----------------------------------------------------------------------
44  * flash_init()
45  *
46  * sets up flash_info and returns size of FLASH (bytes)
47  */
48 unsigned long flash_init (void)
49 {
50         unsigned long size = 0;
51         int i;
52
53         /* Init: no FLASHes known */
54         for (i=0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
55 #if 0
56                 ulong flashbase = (i == 0) ? PHYS_FLASH_1 : PHYS_FLASH_2;
57 #else
58                 ulong flashbase = CONFIG_SYS_FLASH_BASE;
59 #endif
60
61                 memset(&flash_info[i], 0, sizeof(flash_info_t));
62
63                 flash_info[i].size =
64                         flash_get_size((FPW *)flashbase, &flash_info[i]);
65
66                 if (flash_info[i].flash_id == FLASH_UNKNOWN) {
67                         printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx\n",
68                         i, flash_info[i].size);
69                 }
70
71                 size += flash_info[i].size;
72         }
73
74 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
75         /* monitor protection ON by default */
76         flash_protect(FLAG_PROTECT_SET,
77                       CONFIG_SYS_MONITOR_BASE,
78                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
79                       flash_get_info(CONFIG_SYS_MONITOR_BASE));
80 #endif
81
82 #ifdef  CONFIG_ENV_IS_IN_FLASH
83         /* ENV protection ON by default */
84         flash_protect(FLAG_PROTECT_SET,
85                       CONFIG_ENV_ADDR,
86                       CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
87                       flash_get_info(CONFIG_ENV_ADDR));
88 #endif
89
90
91         return size ? size : 1;
92 }
93
94 /*-----------------------------------------------------------------------
95  */
96 static void flash_reset(flash_info_t *info)
97 {
98         FPWV *base = (FPWV *)(info->start[0]);
99
100         /* Put FLASH back in read mode */
101         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
102                 *base = (FPW)0x00FF00FF;        /* Intel Read Mode */
103         else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
104                 *base = (FPW)0x00F000F0;        /* AMD Read Mode */
105 }
106
107 /*-----------------------------------------------------------------------
108  */
109 static void flash_get_offsets (ulong base, flash_info_t *info)
110 {
111         int i;
112
113         /* set up sector start address table */
114         if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
115             && (info->flash_id & FLASH_BTYPE)) {
116                 int bootsect_size;      /* number of bytes/boot sector  */
117                 int sect_size;          /* number of bytes/regular sector */
118
119                 bootsect_size = 0x00002000 * (sizeof(FPW)/2);
120                 sect_size =     0x00010000 * (sizeof(FPW)/2);
121
122                 /* set sector offsets for bottom boot block type        */
123                 for (i = 0; i < 8; ++i) {
124                         info->start[i] = base + (i * bootsect_size);
125                 }
126                 for (i = 8; i < info->sector_count; i++) {
127                         info->start[i] = base + ((i - 7) * sect_size);
128                 }
129         }
130         else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
131                  && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
132
133                 int sect_size;          /* number of bytes/sector */
134
135                 sect_size = 0x00010000 * (sizeof(FPW)/2);
136
137                 /* set up sector start address table (uniform sector type) */
138                 for( i = 0; i < info->sector_count; i++ )
139                         info->start[i] = base + (i * sect_size);
140         }
141 }
142
143 /*-----------------------------------------------------------------------
144  */
145
146 static flash_info_t *flash_get_info(ulong base)
147 {
148         int i;
149         flash_info_t * info;
150
151         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
152                 info = & flash_info[i];
153                 if (info->start[0] <= base && base < info->start[0] + info->size)
154                         break;
155         }
156
157         return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
158 }
159
160 /*-----------------------------------------------------------------------
161  */
162
163 void flash_print_info (flash_info_t *info)
164 {
165         int i;
166         uchar *boottype;
167         uchar *bootletter;
168         char *fmt;
169         uchar botbootletter[] = "B";
170         uchar topbootletter[] = "T";
171         uchar botboottype[] = "bottom boot sector";
172         uchar topboottype[] = "top boot sector";
173
174         if (info->flash_id == FLASH_UNKNOWN) {
175                 printf ("missing or unknown FLASH type\n");
176                 return;
177         }
178
179         switch (info->flash_id & FLASH_VENDMASK) {
180         case FLASH_MAN_AMD:     printf ("AMD ");                break;
181         case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
182         case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
183         case FLASH_MAN_SST:     printf ("SST ");                break;
184         case FLASH_MAN_STM:     printf ("STM ");                break;
185         case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
186         default:                printf ("Unknown Vendor ");     break;
187         }
188
189         /* check for top or bottom boot, if it applies */
190         if (info->flash_id & FLASH_BTYPE) {
191                 boottype = botboottype;
192                 bootletter = botbootletter;
193         }
194         else {
195                 boottype = topboottype;
196                 bootletter = topbootletter;
197         }
198
199         switch (info->flash_id & FLASH_TYPEMASK) {
200         case FLASH_AM640U:
201                 fmt = "29LV641D (64 Mbit, uniform sectors)\n";
202                 break;
203         case FLASH_28F800C3B:
204         case FLASH_28F800C3T:
205                 fmt = "28F800C3%s (8 Mbit, %s)\n";
206                 break;
207         case FLASH_INTEL800B:
208         case FLASH_INTEL800T:
209                 fmt = "28F800B3%s (8 Mbit, %s)\n";
210                 break;
211         case FLASH_28F160C3B:
212         case FLASH_28F160C3T:
213                 fmt = "28F160C3%s (16 Mbit, %s)\n";
214                 break;
215         case FLASH_INTEL160B:
216         case FLASH_INTEL160T:
217                 fmt = "28F160B3%s (16 Mbit, %s)\n";
218                 break;
219         case FLASH_28F320C3B:
220         case FLASH_28F320C3T:
221                 fmt = "28F320C3%s (32 Mbit, %s)\n";
222                 break;
223         case FLASH_INTEL320B:
224         case FLASH_INTEL320T:
225                 fmt = "28F320B3%s (32 Mbit, %s)\n";
226                 break;
227         case FLASH_28F640C3B:
228         case FLASH_28F640C3T:
229                 fmt = "28F640C3%s (64 Mbit, %s)\n";
230                 break;
231         case FLASH_INTEL640B:
232         case FLASH_INTEL640T:
233                 fmt = "28F640B3%s (64 Mbit, %s)\n";
234                 break;
235         default:
236                 fmt = "Unknown Chip Type\n";
237                 break;
238         }
239
240         printf (fmt, bootletter, boottype);
241
242         printf ("  Size: %ld MB in %d Sectors\n",
243                 info->size >> 20,
244                 info->sector_count);
245
246         printf ("  Sector Start Addresses:");
247
248         for (i=0; i<info->sector_count; ++i) {
249                 if ((i % 5) == 0) {
250                         printf ("\n   ");
251                 }
252
253                 printf (" %08lX%s", info->start[i],
254                         info->protect[i] ? " (RO)" : "     ");
255         }
256
257         printf ("\n");
258 }
259
260 /*-----------------------------------------------------------------------
261  */
262
263 /*
264  * The following code cannot be run from FLASH!
265  */
266
267 ulong flash_get_size (FPWV *addr, flash_info_t *info)
268 {
269         /* Write auto select command: read Manufacturer ID */
270
271         /* Write auto select command sequence and test FLASH answer */
272         addr[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* for AMD, Intel ignores this */
273         addr[FLASH_CYCLE2] = (FPW)0x00550055;   /* for AMD, Intel ignores this */
274         addr[FLASH_CYCLE1] = (FPW)0x00900090;   /* selects Intel or AMD */
275
276         /* The manufacturer codes are only 1 byte, so just use 1 byte.
277          * This works for any bus width and any FLASH device width.
278          */
279         udelay(100);
280         switch (addr[0] & 0xff) {
281
282         case (uchar)AMD_MANUFACT:
283                 info->flash_id = FLASH_MAN_AMD;
284                 break;
285
286         case (uchar)INTEL_MANUFACT:
287                 info->flash_id = FLASH_MAN_INTEL;
288                 break;
289
290         default:
291                 info->flash_id = FLASH_UNKNOWN;
292                 info->sector_count = 0;
293                 info->size = 0;
294                 break;
295         }
296
297         /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
298         if (info->flash_id != FLASH_UNKNOWN) switch (addr[1]) {
299
300         case (FPW)AMD_ID_LV640U:        /* 29LV640 and 29LV641 have same ID */
301                 info->flash_id += FLASH_AM640U;
302                 info->sector_count = 128;
303                 info->size = 0x00800000 * (sizeof(FPW)/2);
304                 break;                          /* => 8 or 16 MB        */
305
306         case (FPW)INTEL_ID_28F800C3B:
307                 info->flash_id += FLASH_28F800C3B;
308                 info->sector_count = 23;
309                 info->size = 0x00100000 * (sizeof(FPW)/2);
310                 break;                          /* => 1 or 2 MB         */
311
312         case (FPW)INTEL_ID_28F800B3B:
313                 info->flash_id += FLASH_INTEL800B;
314                 info->sector_count = 23;
315                 info->size = 0x00100000 * (sizeof(FPW)/2);
316                 break;                          /* => 1 or 2 MB         */
317
318         case (FPW)INTEL_ID_28F160C3B:
319                 info->flash_id += FLASH_28F160C3B;
320                 info->sector_count = 39;
321                 info->size = 0x00200000 * (sizeof(FPW)/2);
322                 break;                          /* => 2 or 4 MB         */
323
324         case (FPW)INTEL_ID_28F160B3B:
325                 info->flash_id += FLASH_INTEL160B;
326                 info->sector_count = 39;
327                 info->size = 0x00200000 * (sizeof(FPW)/2);
328                 break;                          /* => 2 or 4 MB         */
329
330         case (FPW)INTEL_ID_28F320C3B:
331                 info->flash_id += FLASH_28F320C3B;
332                 info->sector_count = 71;
333                 info->size = 0x00400000 * (sizeof(FPW)/2);
334                 break;                          /* => 4 or 8 MB         */
335
336         case (FPW)INTEL_ID_28F320B3B:
337                 info->flash_id += FLASH_INTEL320B;
338                 info->sector_count = 71;
339                 info->size = 0x00400000 * (sizeof(FPW)/2);
340                 break;                          /* => 4 or 8 MB         */
341
342         case (FPW)INTEL_ID_28F640C3B:
343                 info->flash_id += FLASH_28F640C3B;
344                 info->sector_count = 135;
345                 info->size = 0x00800000 * (sizeof(FPW)/2);
346                 break;                          /* => 8 or 16 MB        */
347
348         case (FPW)INTEL_ID_28F640B3B:
349                 info->flash_id += FLASH_INTEL640B;
350                 info->sector_count = 135;
351                 info->size = 0x00800000 * (sizeof(FPW)/2);
352                 break;                          /* => 8 or 16 MB        */
353
354         default:
355                 info->flash_id = FLASH_UNKNOWN;
356                 info->sector_count = 0;
357                 info->size = 0;
358                 return (0);                     /* => no or unknown flash */
359         }
360
361         flash_get_offsets((ulong)addr, info);
362
363         /* Put FLASH back in read mode */
364         flash_reset(info);
365
366         return (info->size);
367 }
368
369 /*-----------------------------------------------------------------------
370  */
371
372 int     flash_erase (flash_info_t *info, int s_first, int s_last)
373 {
374         FPWV *addr;
375         int flag, prot, sect;
376         int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
377         ulong start, now, last;
378         int rcode = 0;
379
380         if ((s_first < 0) || (s_first > s_last)) {
381                 if (info->flash_id == FLASH_UNKNOWN) {
382                         printf ("- missing\n");
383                 } else {
384                         printf ("- no sectors to erase\n");
385                 }
386                 return 1;
387         }
388
389         switch (info->flash_id & FLASH_TYPEMASK) {
390         case FLASH_INTEL800B:
391         case FLASH_INTEL160B:
392         case FLASH_INTEL320B:
393         case FLASH_INTEL640B:
394         case FLASH_28F800C3B:
395         case FLASH_28F160C3B:
396         case FLASH_28F320C3B:
397         case FLASH_28F640C3B:
398         case FLASH_AM640U:
399                 break;
400         case FLASH_UNKNOWN:
401         default:
402                 printf ("Can't erase unknown flash type %08lx - aborted\n",
403                         info->flash_id);
404                 return 1;
405         }
406
407         prot = 0;
408         for (sect=s_first; sect<=s_last; ++sect) {
409                 if (info->protect[sect]) {
410                         prot++;
411                 }
412         }
413
414         if (prot) {
415                 printf ("- Warning: %d protected sectors will not be erased!\n",
416                         prot);
417         } else {
418                 printf ("\n");
419         }
420
421         last  = get_timer(0);
422
423         /* Start erase on unprotected sectors */
424         for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
425
426                 if (info->protect[sect] != 0)   /* protected, skip it */
427                         continue;
428
429                 /* Disable interrupts which might cause a timeout here */
430                 flag = disable_interrupts();
431
432                 addr = (FPWV *)(info->start[sect]);
433                 if (intel) {
434                         *addr = (FPW)0x00500050; /* clear status register */
435                         *addr = (FPW)0x00200020; /* erase setup */
436                         *addr = (FPW)0x00D000D0; /* erase confirm */
437                 }
438                 else {
439                         /* must be AMD style if not Intel */
440                         FPWV *base;             /* first address in bank */
441
442                         base = (FPWV *)(info->start[0]);
443                         base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
444                         base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
445                         base[FLASH_CYCLE1] = (FPW)0x00800080;   /* erase mode */
446                         base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
447                         base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
448                         *addr = (FPW)0x00300030;        /* erase sector */
449                 }
450
451                 /* re-enable interrupts if necessary */
452                 if (flag)
453                         enable_interrupts();
454
455                 start = get_timer(0);
456
457                 /* wait at least 50us for AMD, 80us for Intel.
458                  * Let's wait 1 ms.
459                  */
460                 udelay (1000);
461
462                 while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
463                         if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
464                                 printf ("Timeout\n");
465
466                                 if (intel) {
467                                         /* suspend erase        */
468                                         *addr = (FPW)0x00B000B0;
469                                 }
470
471                                 flash_reset(info);      /* reset to read mode */
472                                 rcode = 1;              /* failed */
473                                 break;
474                         }
475
476                         /* show that we're waiting */
477                         if ((get_timer(last)) > CONFIG_SYS_HZ) {/* every second */
478                                 putc ('.');
479                                 last = get_timer(0);
480                         }
481                 }
482
483                 /* show that we're waiting */
484                 if ((get_timer(last)) > CONFIG_SYS_HZ) {        /* every second */
485                         putc ('.');
486                         last = get_timer(0);
487                 }
488
489                 flash_reset(info);      /* reset to read mode   */
490         }
491
492         printf (" done\n");
493         return rcode;
494 }
495
496 /*-----------------------------------------------------------------------
497  * Copy memory to flash, returns:
498  * 0 - OK
499  * 1 - write timeout
500  * 2 - Flash not erased
501  */
502 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
503 {
504         FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
505         int bytes;        /* number of bytes to program in current word         */
506         int left;         /* number of bytes left to program                    */
507         int i, res;
508
509         for (left = cnt, res = 0;
510                  left > 0 && res == 0;
511                  addr += sizeof(data), left -= sizeof(data) - bytes) {
512
513                 bytes = addr & (sizeof(data) - 1);
514                 addr &= ~(sizeof(data) - 1);
515
516                 /* combine source and destination data so can program
517                  * an entire word of 16 or 32 bits
518                  */
519                 for (i = 0; i < sizeof(data); i++) {
520                         data <<= 8;
521                         if (i < bytes || i - bytes >= left )
522                                 data += *((uchar *)addr + i);
523                         else
524                                 data += *src++;
525                 }
526
527                 /* write one word to the flash */
528                 switch (info->flash_id & FLASH_VENDMASK) {
529                 case FLASH_MAN_AMD:
530                         res = write_word_amd(info, (FPWV *)addr, data);
531                         break;
532                 case FLASH_MAN_INTEL:
533                         res = write_word_intel(info, (FPWV *)addr, data);
534                         break;
535                 default:
536                         /* unknown flash type, error! */
537                         printf ("missing or unknown FLASH type\n");
538                         res = 1;        /* not really a timeout, but gives error */
539                         break;
540                 }
541         }
542
543         return (res);
544 }
545
546 /*-----------------------------------------------------------------------
547  * Write a word to Flash for AMD FLASH
548  * A word is 16 or 32 bits, whichever the bus width of the flash bank
549  * (not an individual chip) is.
550  *
551  * returns:
552  * 0 - OK
553  * 1 - write timeout
554  * 2 - Flash not erased
555  */
556 static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
557 {
558         ulong start;
559         int flag;
560         int res = 0;    /* result, assume success       */
561         FPWV *base;             /* first address in flash bank  */
562
563         /* Check if Flash is (sufficiently) erased */
564         if ((*dest & data) != data) {
565                 return (2);
566         }
567
568
569         base = (FPWV *)(info->start[0]);
570
571         /* Disable interrupts which might cause a timeout here */
572         flag = disable_interrupts();
573
574         base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
575         base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
576         base[FLASH_CYCLE1] = (FPW)0x00A000A0;   /* selects program mode */
577
578         *dest = data;           /* start programming the data   */
579
580         /* re-enable interrupts if necessary */
581         if (flag)
582                 enable_interrupts();
583
584         start = get_timer (0);
585
586         /* data polling for D7 */
587         while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
588                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
589                         *dest = (FPW)0x00F000F0;        /* reset bank */
590                         res = 1;
591                 }
592         }
593
594         return (res);
595 }
596
597 /*-----------------------------------------------------------------------
598  * Write a word to Flash for Intel FLASH
599  * A word is 16 or 32 bits, whichever the bus width of the flash bank
600  * (not an individual chip) is.
601  *
602  * returns:
603  * 0 - OK
604  * 1 - write timeout
605  * 2 - Flash not erased
606  */
607 static int write_word_intel (flash_info_t *info, FPWV *dest, FPW data)
608 {
609         ulong start;
610         int flag;
611         int res = 0;    /* result, assume success       */
612
613         /* Check if Flash is (sufficiently) erased */
614         if ((*dest & data) != data) {
615                 return (2);
616         }
617
618         /* Disable interrupts which might cause a timeout here */
619         flag = disable_interrupts();
620
621         *dest = (FPW)0x00500050;        /* clear status register        */
622         *dest = (FPW)0x00FF00FF;        /* make sure in read mode       */
623         *dest = (FPW)0x00400040;        /* program setup                */
624
625         *dest = data;           /* start programming the data   */
626
627         /* re-enable interrupts if necessary */
628         if (flag)
629                 enable_interrupts();
630
631         start = get_timer (0);
632
633         while (res == 0 && (*dest & (FPW)0x00800080) != (FPW)0x00800080) {
634                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
635                         *dest = (FPW)0x00B000B0;        /* Suspend program      */
636                         res = 1;
637                 }
638         }
639
640         if (res == 0 && (*dest & (FPW)0x00100010))
641                 res = 1;        /* write failed, time out error is close enough */
642
643         *dest = (FPW)0x00500050;        /* clear status register        */
644         *dest = (FPW)0x00FF00FF;        /* make sure in read mode       */
645
646         return (res);
647 }