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