source: SVN/rincon/u-boot/board/ivm/flash.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 15.0 KB
Line 
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
27flash_info_t    flash_info[CFG_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       (CFG_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 */
44static ulong flash_get_size (vu_long *addr, flash_info_t *info);
45static int write_data (flash_info_t *info, ulong dest, ulong data);
46static void flash_get_offsets (ulong base, flash_info_t *info);
47
48/*-----------------------------------------------------------------------
49 */
50
51unsigned long flash_init (void)
52{
53        volatile immap_t     *immap  = (immap_t *)CFG_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<CFG_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 = CFG_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
76        memctl->memc_br0 = (CFG_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 *)CFG_FLASH_BASE, &flash_info[0]);
81
82        flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]);
83
84        flash_info[0].size = size_b0;
85
86#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
87        /* monitor protection ON by default */
88        flash_protect(FLAG_PROTECT_SET,
89                      CFG_MONITOR_BASE,
90                      CFG_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 */
107static 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 */
177void 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
265static 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 > CFG_MAX_FLASH_SECT) {
387                printf ("** ERROR: sector count %d > max (%d) **\n",
388                        info->sector_count, CFG_MAX_FLASH_SECT);
389                info->sector_count = CFG_MAX_FLASH_SECT;
390        }
391
392        saddr[0] = 0x00FF;              /* restore read mode */
393
394        return (info->size);
395}
396
397
398/*-----------------------------------------------------------------------
399 */
400
401int     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)) > CFG_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
487int 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 */
561static 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) > CFG_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 */
Note: See TracBrowser for help on using the repository browser.