]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/ivm/flash.c
rename CFG_ macros to CONFIG_SYS
[karo-tx-uboot.git] / board / ivm / flash.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <mpc8xx.h>
26
27 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
28
29 #if defined(CONFIG_ENV_IS_IN_FLASH)
30 # ifndef  CONFIG_ENV_ADDR
31 #  define CONFIG_ENV_ADDR       (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
32 # endif
33 # ifndef  CONFIG_ENV_SIZE
34 #  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
35 # endif
36 # ifndef  CONFIG_ENV_SECT_SIZE
37 #  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
38 # endif
39 #endif
40
41 /*-----------------------------------------------------------------------
42  * Functions
43  */
44 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
45 static int write_data (flash_info_t *info, ulong dest, ulong data);
46 static void flash_get_offsets (ulong base, flash_info_t *info);
47
48 /*-----------------------------------------------------------------------
49  */
50
51 unsigned long flash_init (void)
52 {
53         volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR;
54         volatile memctl8xx_t *memctl = &immap->im_memctl;
55         unsigned long size_b0;
56         int i;
57
58         /* Init: no FLASHes known */
59         for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
60                 flash_info[i].flash_id = FLASH_UNKNOWN;
61         }
62
63         /* Static FLASH Bank configuration here - FIXME XXX */
64
65         size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
66
67         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
68                 printf ("## Unknown FLASH on Bank 0: "
69                         "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
70                         flash_info[0].flash_id,
71                         size_b0, size_b0<<20);
72         }
73
74         /* Remap FLASH according to real size */
75         memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
76         memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | \
77                                 BR_MS_GPCM | BR_PS_16 | BR_V;
78
79         /* Re-do sizing to get full correct info */
80         size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
81
82         flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
83
84         flash_info[0].size = size_b0;
85
86 #if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
87         /* monitor protection ON by default */
88         flash_protect(FLAG_PROTECT_SET,
89                       CONFIG_SYS_MONITOR_BASE,
90                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
91                       &flash_info[0]);
92 #endif
93
94 #ifdef  CONFIG_ENV_IS_IN_FLASH
95         /* ENV protection ON by default */
96         flash_protect(FLAG_PROTECT_SET,
97                       CONFIG_ENV_ADDR,
98                       CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
99                       &flash_info[0]);
100 #endif
101
102         return (size_b0);
103 }
104
105 /*-----------------------------------------------------------------------
106  */
107 static void flash_get_offsets (ulong base, flash_info_t *info)
108 {
109         int i;
110
111         if (info->flash_id == FLASH_UNKNOWN) {
112                 return;
113         }
114
115         switch (info->flash_id & FLASH_VENDMASK) {
116         case FLASH_MAN_MT:
117             if (info->flash_id & FLASH_BTYPE) {
118                 /* set sector offsets for bottom boot block type        */
119                 info->start[0] = base + 0x00000000;
120                 info->start[1] = base + 0x00004000;
121                 info->start[2] = base + 0x00006000;
122                 info->start[3] = base + 0x00008000;
123                 for (i = 4; i < info->sector_count; i++) {
124                         info->start[i] = base + ((i-3) * 0x00020000);
125                 }
126             } else {
127                 /* set sector offsets for top boot block type           */
128                 i = info->sector_count - 1;
129                 info->start[i--] = base + info->size - 0x00004000;
130                 info->start[i--] = base + info->size - 0x00006000;
131                 info->start[i--] = base + info->size - 0x00008000;
132                 for (; i >= 0; i--) {
133                         info->start[i] = base + i * 0x00020000;
134                 }
135             }
136             return;
137
138         case FLASH_MAN_SST:
139             for (i = 0; i < info->sector_count; i++) {
140                 info->start[i] = base + (i * 0x00002000);
141             }
142             return;
143
144         case FLASH_MAN_AMD:
145         case FLASH_MAN_FUJ:
146
147             /* set up sector start address table */
148             if (info->flash_id & FLASH_BTYPE) {
149                 /* set sector offsets for bottom boot block type        */
150                 info->start[0] = base + 0x00000000;
151                 info->start[1] = base + 0x00008000;
152                 info->start[2] = base + 0x0000C000;
153                 info->start[3] = base + 0x00010000;
154                 for (i = 4; i < info->sector_count; i++) {
155                         info->start[i] = base + (i * 0x00020000) - 0x00060000;
156                 }
157             } else {
158                 /* set sector offsets for top boot block type           */
159                 i = info->sector_count - 1;
160                 info->start[i--] = base + info->size - 0x00008000;
161                 info->start[i--] = base + info->size - 0x0000C000;
162                 info->start[i--] = base + info->size - 0x00010000;
163                 for (; i >= 0; i--) {
164                         info->start[i] = base + i * 0x00020000;
165                 }
166             }
167             return;
168         default:
169             printf ("Don't know sector ofsets for flash type 0x%lx\n",
170                 info->flash_id);
171             return;
172         }
173 }
174
175 /*-----------------------------------------------------------------------
176  */
177 void flash_print_info  (flash_info_t *info)
178 {
179         int i;
180
181         if (info->flash_id == FLASH_UNKNOWN) {
182                 printf ("missing or unknown FLASH type\n");
183                 return;
184         }
185
186         switch (info->flash_id & FLASH_VENDMASK) {
187         case FLASH_MAN_AMD:     printf ("AMD ");                break;
188         case FLASH_MAN_FUJ:     printf ("Fujitsu ");            break;
189         case FLASH_MAN_SST:     printf ("SST ");                break;
190         case FLASH_MAN_STM:     printf ("STM ");                break;
191         case FLASH_MAN_MT:      printf ("MT ");                 break;
192         case FLASH_MAN_INTEL:   printf ("Intel ");              break;
193         default:                printf ("Unknown Vendor ");     break;
194         }
195
196         switch (info->flash_id & FLASH_TYPEMASK) {
197         case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
198                                 break;
199         case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
200                                 break;
201         case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
202                                 break;
203         case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
204                                 break;
205         case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
206                                 break;
207         case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
208                                 break;
209         case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
210                                 break;
211         case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
212                                 break;
213         case FLASH_SST200A:     printf ("39xF200A (2M = 128K x 16)\n");
214                                 break;
215         case FLASH_SST400A:     printf ("39xF400A (4M = 256K x 16)\n");
216                                 break;
217         case FLASH_SST800A:     printf ("39xF800A (8M = 512K x 16)\n");
218                                 break;
219         case FLASH_STM800AB:    printf ("M29W800AB (8M = 512K x 16)\n");
220                                 break;
221         case FLASH_28F008S5:    printf ("28F008S5 (1M = 64K x 16)\n");
222                                 break;
223         case FLASH_28F400_T:    printf ("28F400B3 (4Mbit, top boot sector)\n");
224                                 break;
225         case FLASH_28F400_B:    printf ("28F400B3 (4Mbit, bottom boot sector)\n");
226                                 break;
227         default:                printf ("Unknown Chip Type\n");
228                                 break;
229         }
230
231         if (info->size >= (1 << 20)) {
232                 i = 20;
233         } else {
234                 i = 10;
235         }
236         printf ("  Size: %ld %cB in %d Sectors\n",
237                 info->size >> i,
238                 (i == 20) ? 'M' : 'k',
239                 info->sector_count);
240
241         printf ("  Sector Start Addresses:");
242         for (i=0; i<info->sector_count; ++i) {
243                 if ((i % 5) == 0)
244                         printf ("\n   ");
245                 printf (" %08lX%s",
246                         info->start[i],
247                         info->protect[i] ? " (RO)" : "     "
248                 );
249         }
250         printf ("\n");
251         return;
252 }
253
254 /*-----------------------------------------------------------------------
255  */
256
257
258 /*-----------------------------------------------------------------------
259  */
260
261 /*
262  * The following code cannot be run from FLASH!
263  */
264
265 static ulong flash_get_size (vu_long *addr, flash_info_t *info)
266 {
267         ushort value;
268         vu_short *saddr = (vu_short *)addr;
269
270         /* Read Manufacturer ID */
271         saddr[0] = 0x0090;
272         value = saddr[0];
273
274         switch (value) {
275         case (AMD_MANUFACT & 0xFFFF):
276                 info->flash_id = FLASH_MAN_AMD;
277                 break;
278         case (FUJ_MANUFACT & 0xFFFF):
279                 info->flash_id = FLASH_MAN_FUJ;
280                 break;
281         case (SST_MANUFACT & 0xFFFF):
282                 info->flash_id = FLASH_MAN_SST;
283                 break;
284         case (STM_MANUFACT & 0xFFFF):
285                 info->flash_id = FLASH_MAN_STM;
286                 break;
287         case (MT_MANUFACT & 0xFFFF):
288                 info->flash_id = FLASH_MAN_MT;
289                 break;
290         default:
291                 info->flash_id = FLASH_UNKNOWN;
292                 info->sector_count = 0;
293                 info->size = 0;
294                 saddr[0] = 0x00FF;              /* restore read mode */
295                 return (0);                     /* no or unknown flash  */
296         }
297
298         value = saddr[1];                       /* device ID            */
299
300         switch (value) {
301         case (AMD_ID_LV400T & 0xFFFF):
302                 info->flash_id += FLASH_AM400T;
303                 info->sector_count = 11;
304                 info->size = 0x00100000;
305                 break;                          /* => 1 MB              */
306
307         case (AMD_ID_LV400B & 0xFFFF):
308                 info->flash_id += FLASH_AM400B;
309                 info->sector_count = 11;
310                 info->size = 0x00100000;
311                 break;                          /* => 1 MB              */
312
313         case (AMD_ID_LV800T & 0xFFFF):
314                 info->flash_id += FLASH_AM800T;
315                 info->sector_count = 19;
316                 info->size = 0x00200000;
317                 break;                          /* => 2 MB              */
318
319         case (AMD_ID_LV800B & 0xFFFF):
320                 info->flash_id += FLASH_AM800B;
321                 info->sector_count = 19;
322                 info->size = 0x00200000;
323                 break;                          /* => 2 MB              */
324
325         case (AMD_ID_LV160T & 0xFFFF):
326                 info->flash_id += FLASH_AM160T;
327                 info->sector_count = 35;
328                 info->size = 0x00400000;
329                 break;                          /* => 4 MB              */
330
331         case (AMD_ID_LV160B & 0xFFFF):
332                 info->flash_id += FLASH_AM160B;
333                 info->sector_count = 35;
334                 info->size = 0x00400000;
335                 break;                          /* => 4 MB              */
336 #if 0   /* enable when device IDs are available */
337         case (AMD_ID_LV320T & 0xFFFF):
338                 info->flash_id += FLASH_AM320T;
339                 info->sector_count = 67;
340                 info->size = 0x00800000;
341                 break;                          /* => 8 MB              */
342
343         case (AMD_ID_LV320B & 0xFFFF):
344                 info->flash_id += FLASH_AM320B;
345                 info->sector_count = 67;
346                 info->size = 0x00800000;
347                 break;                          /* => 8 MB              */
348 #endif
349         case (SST_ID_xF200A & 0xFFFF):
350                 info->flash_id += FLASH_SST200A;
351                 info->sector_count = 64;        /* 39xF200A ID ( 2M = 128K x 16 ) */
352                 info->size = 0x00080000;
353                 break;
354         case (SST_ID_xF400A & 0xFFFF):
355                 info->flash_id += FLASH_SST400A;
356                 info->sector_count = 128;       /* 39xF400A ID ( 4M = 256K x 16 ) */
357                 info->size = 0x00100000;
358                 break;
359         case (SST_ID_xF800A & 0xFFFF):
360                 info->flash_id += FLASH_SST800A;
361                 info->sector_count = 256;       /* 39xF800A ID ( 8M = 512K x 16 ) */
362                 info->size = 0x00200000;
363                 break;                          /* => 2 MB              */
364         case (STM_ID_x800AB & 0xFFFF):
365                 info->flash_id += FLASH_STM800AB;
366                 info->sector_count = 19;
367                 info->size = 0x00200000;
368                 break;                          /* => 2 MB              */
369         case (MT_ID_28F400_T & 0xFFFF):
370                 info->flash_id += FLASH_28F400_T;
371                 info->sector_count = 7;
372                 info->size = 0x00080000;
373                 break;                          /* => 512 kB            */
374         case (MT_ID_28F400_B & 0xFFFF):
375                 info->flash_id += FLASH_28F400_B;
376                 info->sector_count = 7;
377                 info->size = 0x00080000;
378                 break;                          /* => 512 kB            */
379         default:
380                 info->flash_id = FLASH_UNKNOWN;
381                 saddr[0] = 0x00FF;              /* restore read mode */
382                 return (0);                     /* => no or unknown flash */
383
384         }
385
386         if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
387                 printf ("** ERROR: sector count %d > max (%d) **\n",
388                         info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
389                 info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
390         }
391
392         saddr[0] = 0x00FF;              /* restore read mode */
393
394         return (info->size);
395 }
396
397
398 /*-----------------------------------------------------------------------
399  */
400
401 int     flash_erase (flash_info_t *info, int s_first, int s_last)
402 {
403         int flag, prot, sect;
404         ulong start, now, last;
405
406         if ((s_first < 0) || (s_first > s_last)) {
407                 if (info->flash_id == FLASH_UNKNOWN) {
408                         printf ("- missing\n");
409                 } else {
410                         printf ("- no sectors to erase\n");
411                 }
412                 return 1;
413         }
414
415         if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_MT) {
416                 printf ("Can erase only MT flash types - aborted\n");
417                 return 1;
418         }
419
420         prot = 0;
421         for (sect=s_first; sect<=s_last; ++sect) {
422                 if (info->protect[sect]) {
423                         prot++;
424                 }
425         }
426
427         if (prot) {
428                 printf ("- Warning: %d protected sectors will not be erased!\n",
429                         prot);
430         } else {
431                 printf ("\n");
432         }
433
434         start = get_timer (0);
435         last  = start;
436         /* Start erase on unprotected sectors */
437         for (sect = s_first; sect<=s_last; sect++) {
438                 if (info->protect[sect] == 0) { /* not protected */
439                         vu_short *addr = (vu_short *)(info->start[sect]);
440                         unsigned short status;
441
442                         /* Disable interrupts which might cause a timeout here */
443                         flag = disable_interrupts();
444
445                         *addr = 0x0050; /* clear status register */
446                         *addr = 0x0020; /* erase setup */
447                         *addr = 0x00D0; /* erase confirm */
448
449                         /* re-enable interrupts if necessary */
450                         if (flag)
451                                 enable_interrupts();
452
453                         /* wait at least 80us - let's wait 1 ms */
454                         udelay (1000);
455
456                         while (((status = *addr) & 0x0080) != 0x0080) {
457                                 if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
458                                         printf ("Timeout\n");
459                                         *addr = 0x00FF; /* reset to read mode */
460                                         return 1;
461                                 }
462
463                                 /* show that we're waiting */
464                                 if ((now - last) > 1000) {      /* every second */
465                                         putc ('.');
466                                         last = now;
467                                 }
468                         }
469
470                         *addr = 0x00FF; /* reset to read mode */
471                 }
472         }
473         printf (" done\n");
474         return 0;
475 }
476
477 /*-----------------------------------------------------------------------
478  * Copy memory to flash, returns:
479  * 0 - OK
480  * 1 - write timeout
481  * 2 - Flash not erased
482  * 4 - Flash not identified
483  */
484
485 #define FLASH_WIDTH     2       /* flash bus width in bytes */
486
487 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
488 {
489         ulong cp, wp, data;
490         int i, l, rc;
491
492         if (info->flash_id == FLASH_UNKNOWN) {
493                 return 4;
494         }
495
496         wp = (addr & ~(FLASH_WIDTH-1)); /* get lower FLASH_WIDTH aligned address */
497
498         /*
499          * handle unaligned start bytes
500          */
501         if ((l = addr - wp) != 0) {
502                 data = 0;
503                 for (i=0, cp=wp; i<l; ++i, ++cp) {
504                         data = (data << 8) | (*(uchar *)cp);
505                 }
506                 for (; i<FLASH_WIDTH && cnt>0; ++i) {
507                         data = (data << 8) | *src++;
508                         --cnt;
509                         ++cp;
510                 }
511                 for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) {
512                         data = (data << 8) | (*(uchar *)cp);
513                 }
514
515                 if ((rc = write_data(info, wp, data)) != 0) {
516                         return (rc);
517                 }
518                 wp += FLASH_WIDTH;
519         }
520
521         /*
522          * handle FLASH_WIDTH aligned part
523          */
524         while (cnt >= FLASH_WIDTH) {
525                 data = 0;
526                 for (i=0; i<FLASH_WIDTH; ++i) {
527                         data = (data << 8) | *src++;
528                 }
529                 if ((rc = write_data(info, wp, data)) != 0) {
530                         return (rc);
531                 }
532                 wp  += FLASH_WIDTH;
533                 cnt -= FLASH_WIDTH;
534         }
535
536         if (cnt == 0) {
537                 return (0);
538         }
539
540         /*
541          * handle unaligned tail bytes
542          */
543         data = 0;
544         for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) {
545                 data = (data << 8) | *src++;
546                 --cnt;
547         }
548         for (; i<FLASH_WIDTH; ++i, ++cp) {
549                 data = (data << 8) | (*(uchar *)cp);
550         }
551
552         return (write_data(info, wp, data));
553 }
554
555 /*-----------------------------------------------------------------------
556  * Write a word to Flash, returns:
557  * 0 - OK
558  * 1 - write timeout
559  * 2 - Flash not erased
560  */
561 static int write_data (flash_info_t *info, ulong dest, ulong data)
562 {
563         vu_short *addr = (vu_short *)dest;
564         ushort sdata = (ushort)data;
565         ushort status;
566         ulong start;
567         int flag;
568
569         /* Check if Flash is (sufficiently) erased */
570         if ((*addr & sdata) != sdata) {
571                 return (2);
572         }
573         /* Disable interrupts which might cause a timeout here */
574         flag = disable_interrupts();
575
576         *addr = 0x0040;         /* write setup */
577         *addr = sdata;
578
579         /* re-enable interrupts if necessary */
580         if (flag)
581                 enable_interrupts();
582
583         start = get_timer (0);
584
585         while (((status = *addr) & 0x0080) != 0x0080) {
586                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
587                         *addr = 0x00FF; /* restore read mode */
588                         return (1);
589                 }
590         }
591
592         *addr = 0x00FF;         /* restore read mode */
593
594         return (0);
595 }
596
597 /*-----------------------------------------------------------------------
598  */