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

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

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

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