source: SVN/rincon/u-boot/board/mvblue/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: 15.5 KB
Line 
1/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 * (C) Copyright 2001-2003
5 *
6 * Changes for MATRIX Vision mvBLUE devices
7 * MATRIX Vision GmbH / hg,as info@matrix-vision.de
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25#include <common.h>
26#include <mpc824x.h>
27
28#if 0
29        #define mvdebug(p) printf ##p
30#else
31        #define mvdebug(p)
32#endif
33
34flash_info_t    flash_info[CFG_MAX_FLASH_BANKS];
35
36#define FLASH_BUS_WIDTH         8
37
38#if (FLASH_BUS_WIDTH==32)
39        #define FLASH_DATA_MASK 0xffffffff
40        #define FLASH_SHIFT 1
41        #define FDT     vu_long
42#elif (FLASH_BUS_WIDTH==16)
43        #define FLASH_DATA_MASK 0xff
44        #define FLASH_SHIFT 0
45        #define FDT     vu_short
46#elif (FLASH_BUS_WIDTH==8)
47        #define FLASH_DATA_MASK 0xff
48        #define FLASH_SHIFT 0
49        #define FDT     vu_char
50#else
51        #error FLASH_BUS_WIDTH undefined
52#endif
53
54/*-----------------------------------------------------------------------
55 * Functions
56 */
57static ulong flash_get_size (vu_long *address, flash_info_t *info);
58static int write_word (flash_info_t *info, ulong dest, ulong data);
59static void flash_get_offsets (ulong base, flash_info_t *info);
60
61/*-----------------------------------------------------------------------
62 */
63unsigned long flash_init (void)
64{
65        unsigned long size_b0;
66        int i;
67
68        for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
69                flash_info[i].flash_id = FLASH_UNKNOWN;
70        }
71
72        size_b0 = flash_get_size((vu_long *)0xffc00000, &flash_info[0]);
73
74        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
75                printf ("## Unknown FLASH : Size = 0x%08lx = %ld MB\n",
76                        size_b0, size_b0<<20);
77        }
78
79        flash_get_offsets (0xffc00000, &flash_info[0]);
80        flash_info[0].size = size_b0;
81
82        /* monitor protection OFF by default */
83        flash_protect ( FLAG_PROTECT_CLEAR, 0xffc00000, 0x2000, flash_info );
84
85        return size_b0;
86}
87
88/*-----------------------------------------------------------------------
89 */
90static void flash_get_offsets (ulong base, flash_info_t *info)
91{
92        int i;
93
94        /* set up sector start address table */
95        if (info->flash_id & FLASH_BTYPE)
96        {       /* bottom boot sector types - these are the useful ones! */
97                /* set sector offsets for bottom boot block type */
98                if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B)
99                {       /* AMDLV320B has 8 x 8k bottom boot sectors */
100                        for (i = 0; i < 8; i++)                                                                                         /* +8k          */
101                                info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT));
102                        for (; i < info->sector_count; i++)                                                                     /* +64k         */
103                                info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00070000 << FLASH_SHIFT);
104                }
105                else
106                {       /* other types have 4 bottom boot sectors (16,8,8,32) */
107                        i = 0;
108                        info->start[i++] = base +  0x00000000;                                                          /* -            */
109                        info->start[i++] = base + (0x00004000 << FLASH_SHIFT);                          /* +16k         */
110                        info->start[i++] = base + (0x00006000 << FLASH_SHIFT);                          /* +8k          */
111                        info->start[i++] = base + (0x00008000 << FLASH_SHIFT);                          /* +8k          */
112                        info->start[i++] = base + (0x00010000 << FLASH_SHIFT);                          /* +32k         */
113                        for (; i < info->sector_count; i++)                                                                     /* +64k         */
114                                info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00030000 << FLASH_SHIFT);
115                }
116        }
117        else
118        {       /* top boot sector types - not so useful */
119                /* set sector offsets for top boot block type */
120                if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T)
121                {       /* AMDLV320T has 8 x 8k top boot sectors */
122                        for (i = 0; i < info->sector_count - 8; i++)                                            /* +64k         */
123                                info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT));
124                        for (; i < info->sector_count; i++)                                                                     /* +8k          */
125                                info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT));
126                }
127                else
128                {       /* other types have 4 top boot sectors (32,8,8,16) */
129                        for (i = 0; i < info->sector_count - 4; i++)                                            /* +64k         */
130                                info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT));
131
132                        info->start[i++] = base + info->size - (0x00010000 << FLASH_SHIFT);     /* -32k         */
133                        info->start[i++] = base + info->size - (0x00008000 << FLASH_SHIFT);     /* -8k          */
134                        info->start[i++] = base + info->size - (0x00006000 << FLASH_SHIFT);     /* -8k          */
135                        info->start[i]   = base + info->size - (0x00004000 << FLASH_SHIFT);     /* -16k         */
136                }
137        }
138}
139
140/*-----------------------------------------------------------------------
141 */
142void flash_print_info  (flash_info_t *info)
143{
144        int i;
145
146        if (info->flash_id == FLASH_UNKNOWN) {
147                printf ("missing or unknown FLASH type\n");
148                return;
149        }
150
151        switch (info->flash_id & FLASH_VENDMASK) {
152        case FLASH_MAN_AMD:     printf ("AMD ");                break;
153        case FLASH_MAN_FUJ:     printf ("FUJITSU ");    break;
154        case FLASH_MAN_STM:     printf ("ST ");                 break;
155        default:                printf ("Unknown Vendor ");     break;
156        }
157
158        switch (info->flash_id & FLASH_TYPEMASK) {
159        case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
160                                break;
161        case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
162                                break;
163        case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
164                                break;
165        case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
166                                break;
167        case FLASH_STMW320DB:   printf ("M29W320B (32 Mbit, bottom boot sect)\n");
168                                break;
169        case FLASH_STMW320DT:   printf ("M29W320T (32 Mbit, top boot sector)\n");
170                                break;
171        default:                printf ("Unknown Chip Type\n");
172                                break;
173        }
174
175        printf ("  Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count);
176
177        printf ("  Sector Start Addresses:");
178        for (i=0; i<info->sector_count; ++i) {
179                if ((i % 5) == 0)
180                        printf ("\n   ");
181                printf (" %08lX%s", info->start[i], info->protect[i] ? " (RO)" : "     ");
182        }
183        printf ("\n");
184}
185
186/*
187 * The following code cannot be run from FLASH!
188 */
189
190#define AMD_ID_LV160T_MVS       (AMD_ID_LV160T & FLASH_DATA_MASK)
191#define AMD_ID_LV160B_MVS       (AMD_ID_LV160B & FLASH_DATA_MASK)
192#define AMD_ID_LV320T_MVS       (AMD_ID_LV320T & FLASH_DATA_MASK)
193#define AMD_ID_LV320B_MVS       (AMD_ID_LV320B & FLASH_DATA_MASK)
194#define STM_ID_W320DT_MVS       (STM_ID_29W320DT & FLASH_DATA_MASK)
195#define STM_ID_W320DB_MVS       (STM_ID_29W320DB & FLASH_DATA_MASK)
196#define AMD_MANUFACT_MVS        (AMD_MANUFACT  & FLASH_DATA_MASK)
197#define FUJ_MANUFACT_MVS        (FUJ_MANUFACT  & FLASH_DATA_MASK)
198#define STM_MANUFACT_MVS        (STM_MANUFACT  & FLASH_DATA_MASK)
199
200#if (FLASH_BUS_WIDTH >= 16)
201        #define AUTOSELECT_ADDR1        0x0555
202        #define AUTOSELECT_ADDR2        0x02AA
203        #define AUTOSELECT_ADDR3        AUTOSELECT_ADDR1
204#else
205        #define AUTOSELECT_ADDR1        0x0AAA
206        #define AUTOSELECT_ADDR2        0x0555
207        #define AUTOSELECT_ADDR3        AUTOSELECT_ADDR1
208#endif
209
210#define AUTOSELECT_DATA1        (0x00AA00AA & FLASH_DATA_MASK)
211#define AUTOSELECT_DATA2        (0x00550055 & FLASH_DATA_MASK)
212#define AUTOSELECT_DATA3        (0x00900090 & FLASH_DATA_MASK)
213
214#define RESET_BANK_DATA         (0x00F000F0 & FLASH_DATA_MASK)
215
216
217static ulong flash_get_size (vu_long *address, flash_info_t *info)
218{
219        short i;
220        FDT value;
221        FDT *addr = (FDT *)address;
222
223        ulong base = (ulong)address;
224        addr[AUTOSELECT_ADDR1] = AUTOSELECT_DATA1;
225        addr[AUTOSELECT_ADDR2] = AUTOSELECT_DATA2;
226        addr[AUTOSELECT_ADDR3] = AUTOSELECT_DATA3;
227        __asm__ __volatile__("sync");
228
229        udelay(180);
230
231        value = addr[0];                        /* manufacturer ID      */
232        switch (value) {
233        case AMD_MANUFACT_MVS:
234                info->flash_id = FLASH_MAN_AMD;
235                break;
236        case FUJ_MANUFACT_MVS:
237                info->flash_id = FLASH_MAN_FUJ;
238                break;
239        case STM_MANUFACT_MVS:
240                info->flash_id = FLASH_MAN_STM;
241                break;
242        default:
243                info->flash_id = FLASH_UNKNOWN;
244                info->sector_count = 0;
245                info->size = 0;
246                return (0);                     /* no or unknown flash  */
247        }
248#if (FLASH_BUS_WIDTH >= 16)
249        value = addr[1];                        /* device ID            */
250#else
251        value = addr[2];                        /* device ID            */
252#endif
253
254        switch (value) {
255        case AMD_ID_LV160T_MVS:
256                info->flash_id += FLASH_AM160T;
257                info->sector_count = 37;
258                info->size = (0x00200000 << FLASH_SHIFT);
259                break;                          /* => 2 or 4 MB         */
260
261        case AMD_ID_LV160B_MVS:
262                info->flash_id += FLASH_AM160B;
263                info->sector_count = 37;
264                info->size = (0x00200000 << FLASH_SHIFT);
265                break;                          /* => 2 or 4 MB         */
266
267        case AMD_ID_LV320T_MVS:
268                info->flash_id += FLASH_AM320T;
269                info->sector_count = 71;
270                info->size = (0x00400000 << FLASH_SHIFT);
271                break;                          /* => 4 or 8 MB         */
272
273        case AMD_ID_LV320B_MVS:
274                info->flash_id += FLASH_AM320B;
275                info->sector_count = 71;
276                info->size = (0x00400000 << FLASH_SHIFT);
277                break;                          /* => 4 or 8MB          */
278
279        case STM_ID_W320DT_MVS:
280                info->flash_id += FLASH_STMW320DT;
281                info->sector_count = 67;
282                info->size = (0x00400000 << FLASH_SHIFT);
283                break;                          /* => 4 or 8 MB         */
284
285        case STM_ID_W320DB_MVS:
286                info->flash_id += FLASH_STMW320DB;
287                info->sector_count = 67;
288                info->size = (0x00400000 << FLASH_SHIFT);
289                break;                          /* => 4 or 8MB          */
290
291        default:
292                info->flash_id = FLASH_UNKNOWN;
293                return (0);                     /* => no or unknown flash */
294
295        }
296
297        /* set up sector start address table */
298        flash_get_offsets (base, info);
299
300        /* check for protected sectors */
301        for (i = 0; i < info->sector_count; i++) {
302                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
303                /* D0 = 1 if protected */
304                addr = (FDT *)(info->start[i]);
305                info->protect[i] = addr[2] & 1;
306        }
307
308        /*
309         * Prevent writes to uninitialized FLASH.
310         */
311        if (info->flash_id != FLASH_UNKNOWN) {
312                addr = (FDT *)info->start[0];
313                *addr = RESET_BANK_DATA;        /* reset bank */
314        }
315        return (info->size);
316}
317
318
319/*-----------------------------------------------------------------------
320 */
321
322#if (FLASH_BUS_WIDTH >= 16)
323        #define ERASE_ADDR1 0x0555
324        #define ERASE_ADDR2 0x02AA
325#else
326        #define ERASE_ADDR1 0x0AAA
327        #define ERASE_ADDR2 0x0555
328#endif
329
330#define ERASE_ADDR3 ERASE_ADDR1
331#define ERASE_ADDR4 ERASE_ADDR1
332#define ERASE_ADDR5 ERASE_ADDR2
333
334#define ERASE_DATA1 (0x00AA00AA & FLASH_DATA_MASK)
335#define ERASE_DATA2 (0x00550055 & FLASH_DATA_MASK)
336#define ERASE_DATA3 (0x00800080 & FLASH_DATA_MASK)
337#define ERASE_DATA4 ERASE_DATA1
338#define ERASE_DATA5 ERASE_DATA2
339
340#define ERASE_SECTOR_DATA       (0x00300030 & FLASH_DATA_MASK)
341#define ERASE_CHIP_DATA         (0x00100010 & FLASH_DATA_MASK)
342#define ERASE_CONFIRM_DATA      (0x00800080 & FLASH_DATA_MASK)
343
344int     flash_erase (flash_info_t *info, int s_first, int s_last)
345{
346        FDT *addr = (FDT *)(info->start[0]);
347
348        int prot, sect, l_sect, flag;
349        ulong start, now, last;
350
351        __asm__ __volatile__ ("sync");
352        addr[0] = 0xf0;
353        udelay(1000);
354
355        printf("\nflash_erase: first = %d @ 0x%08lx\n", s_first, info->start[s_first] );
356        printf("             last  = %d @ 0x%08lx\n", s_last , info->start[s_last ] );
357
358        if ((s_first < 0) || (s_first > s_last)) {
359                if (info->flash_id == FLASH_UNKNOWN) {
360                        printf ("- missing\n");
361                } else {
362                        printf ("- no sectors to erase\n");
363                }
364                return 1;
365        }
366
367        if ((info->flash_id == FLASH_UNKNOWN) || (info->flash_id > FLASH_AMD_COMP)) {
368                printf ("Can't erase unknown flash type %08lx - aborted\n", info->flash_id);
369                return 1;
370        }
371
372        prot = 0;
373        for (sect=s_first; sect<=s_last; ++sect) {
374                if (info->protect[sect]) {
375                        prot++;
376                }
377        }
378
379        if (prot) {
380                printf ("- Warning: %d protected sectors will not be erased!\n",
381                        prot);
382        } else {
383                printf ("\n");
384        }
385
386        l_sect = -1;
387
388        /* Disable interrupts which might cause a timeout here */
389        flag = disable_interrupts();
390
391        addr[ERASE_ADDR1] = ERASE_DATA1;
392        addr[ERASE_ADDR2] = ERASE_DATA2;
393        addr[ERASE_ADDR3] = ERASE_DATA3;
394        addr[ERASE_ADDR4] = ERASE_DATA4;
395        addr[ERASE_ADDR5] = ERASE_DATA5;
396
397        for (sect = s_first; sect <= s_last; sect++) {
398                if (info->protect[sect] == 0) {
399                        addr = (FDT *)(info->start[sect]);
400                        addr[0] = ERASE_SECTOR_DATA;
401                        l_sect = sect;
402                }
403        }
404
405        if (flag)
406                enable_interrupts();
407
408        /*
409         * We wait for the last triggered sector
410         */
411        if (l_sect < 0)
412                goto DONE;
413
414        start = get_timer (0);
415        last  = start;
416        addr = (FDT *)(info->start[l_sect]);
417
418        while ((addr[0] & ERASE_CONFIRM_DATA) != ERASE_CONFIRM_DATA) {
419                if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
420                        printf ("Timeout\n");
421                        return 1;
422                }
423                /* show that we're waiting */
424                if ((now - last) > 1000) {      /* every second */
425                        putc ('.');
426                        last = now;
427                }
428        }
429
430DONE:
431        printf (" done\n");
432        return 0;
433}
434
435/*-----------------------------------------------------------------------
436 * Copy memory to flash, returns:
437 * 0 - OK
438 * 1 - write timeout
439 * 2 - Flash not erased
440 */
441
442int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
443{
444#define BUFF_INC 4
445        ulong cp, wp, data;
446        int i, l, rc;
447
448        mvdebug (("+write_buff %p ==> 0x%08lx, count = 0x%08lx\n", src, addr, cnt));
449
450        wp = (addr & ~3);       /* get lower word aligned address */
451        /*
452         * handle unaligned start bytes
453         */
454        if ((l = addr - wp) != 0) {
455                mvdebug ((" handle unaligned start bytes (cnt = 0x%08lx)\n", cnt));
456                data = 0;
457                for (i=0, cp=wp; i<l; ++i, ++cp) {
458                        data = (data << 8) | (*(uchar *)cp);
459                }
460                for (; i<BUFF_INC && cnt>0; ++i) {
461                        data = (data << 8) | *src++;
462                        --cnt;
463                        ++cp;
464                }
465                for (; cnt==0 && i<BUFF_INC; ++i, ++cp) {
466                        data = (data << 8) | (*(uchar *)cp);
467                }
468
469                if ((rc = write_word(info, wp, data)) != 0) {
470                        return (rc);
471                }
472                wp += BUFF_INC;
473        }
474
475        /*
476         * handle (half)word aligned part
477         */
478        mvdebug ((" handle word aligned part (cnt = 0x%08lx)\n", cnt));
479        while (cnt >= BUFF_INC) {
480                data = 0;
481                for (i=0; i<BUFF_INC; ++i) {
482                        data = (data << 8) | *src++;
483                }
484                if ((rc = write_word(info, wp, data)) != 0) {
485                        return (rc);
486                }
487                wp  += BUFF_INC;
488                cnt -= BUFF_INC;
489        }
490
491        if (cnt == 0) {
492                return (0);
493        }
494
495        /*
496         * handle unaligned tail bytes
497         */
498        mvdebug ((" handle unaligned tail bytes (cnt = 0x%08lx)\n", cnt));
499        data = 0;
500        for (i=0, cp=wp; i<BUFF_INC && cnt>0; ++i, ++cp) {
501                data = (data << 8) | *src++;
502                --cnt;
503        }
504        for (; i<BUFF_INC; ++i, ++cp) {
505                data = (data << 8) | (*(uchar *)cp);
506        }
507
508        return (write_word(info, wp, data));
509}
510
511#if (FLASH_BUS_WIDTH >= 16)
512        #define WRITE_ADDR1 0x0555
513        #define WRITE_ADDR2 0x02AA
514#else
515        #define WRITE_ADDR1 0x0AAA
516        #define WRITE_ADDR2 0x0555
517        #define WRITE_ADDR3 WRITE_ADDR1
518#endif
519
520#define WRITE_DATA1 (0x00AA00AA & FLASH_DATA_MASK)
521#define WRITE_DATA2 (0x00550055 & FLASH_DATA_MASK)
522#define WRITE_DATA3 (0x00A000A0 & FLASH_DATA_MASK)
523
524#define WRITE_CONFIRM_DATA ERASE_CONFIRM_DATA
525
526/*-----------------------------------------------------------------------
527 * Write a byte to Flash, returns:
528 * 0 - OK
529 * 1 - write timeout
530 * 2 - Flash not erased
531 */
532static int write_char (flash_info_t *info, ulong dest, uchar data)
533{
534        vu_char *addr = (vu_char *)(info->start[0]);
535        ulong start;
536        int flag;
537
538        /* Check if Flash is (sufficiently) erased */
539        if ((*((vu_char *)dest) & data) != data) {
540                printf(" *** ERROR: Flash not erased !\n");
541                return (2);
542        }
543        flag = disable_interrupts();
544
545        addr[WRITE_ADDR1] = WRITE_DATA1;
546        addr[WRITE_ADDR2] = WRITE_DATA2;
547        addr[WRITE_ADDR3] = WRITE_DATA3;
548        *((vu_char *)dest) = data;
549
550        if (flag)
551                enable_interrupts();
552
553        /* data polling for D7 */
554        start = get_timer (0);
555        addr = (vu_char *)dest;
556        while (( (*addr) & WRITE_CONFIRM_DATA) != (data & WRITE_CONFIRM_DATA)) {
557                if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
558                        printf(" *** ERROR: Flash write timeout !");
559                        return (1);
560                }
561        }
562        mvdebug (("-write_byte\n"));
563        return (0);
564}
565
566/*-----------------------------------------------------------------------
567 * Write a word to Flash, returns:
568 * 0 - OK
569 * 1 - write timeout
570 * 2 - Flash not erased
571 */
572static int write_word (flash_info_t *info, ulong dest, ulong data)
573{
574        int i,
575                result = 0;
576
577        mvdebug (("+write_word : 0x%08lx @ 0x%08lx\n", data, dest));
578        for ( i=0; (i < 4) && (result == 0); i++, dest+=1 )
579                result = write_char (info, dest, (data >> (8*(3-i))) & 0xff );
580        mvdebug (("-write_word\n"));
581        return result;
582}
583/*---------------------------------------------------------------- */
Note: See TracBrowser for help on using the repository browser.