source: SVN/rincon/u-boot/board/jse/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: 12.6 KB
Line 
1/*
2 * (C) Copyright 2000-2004
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/*
25 * Modified 4/5/2001
26 * Wait for completion of each sector erase command issued
27 * 4/5/2001
28 * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
29 */
30
31#include <common.h>
32#include <ppc4xx.h>
33#include <asm/processor.h>
34
35#if CFG_MAX_FLASH_BANKS != 1
36#error "CFG_MAX_FLASH_BANKS must be 1"
37#endif
38flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips */
39
40/*-----------------------------------------------------------------------
41 * Functions
42 */
43static ulong flash_get_size (vu_long * addr, flash_info_t * info);
44static int write_word (flash_info_t * info, ulong dest, ulong data);
45static void flash_get_offsets (ulong base, flash_info_t * info);
46
47#define ADDR0           0x5555
48#define ADDR1           0x2aaa
49#define FLASH_WORD_SIZE unsigned char
50
51/*-----------------------------------------------------------------------
52 */
53
54unsigned long flash_init (void)
55{
56        unsigned long size_b0;
57
58        /* Init: no FLASHes known */
59        flash_info[0].flash_id = FLASH_UNKNOWN;
60
61        /* Static FLASH Bank configuration here - FIXME XXX */
62
63        size_b0 = flash_get_size ((vu_long *) FLASH_BASE0_PRELIM, &flash_info[0]);
64
65        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
66                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
67                        size_b0, size_b0 << 20);
68        }
69
70        /* Only one bank */
71        /* Setup offsets */
72        flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
73
74        /* Monitor protection ON by default */
75        (void) flash_protect (FLAG_PROTECT_SET,
76                              FLASH_BASE0_PRELIM,
77                              FLASH_BASE0_PRELIM + monitor_flash_len - 1,
78                              &flash_info[0]);
79        flash_info[0].size = size_b0;
80
81        return size_b0;
82}
83
84
85/*-----------------------------------------------------------------------
86 */
87/*
88 * This implementation assumes that the flash chips are uniform sector
89 * devices. This is true for all likely JSE devices.
90 */
91static void flash_get_offsets (ulong base, flash_info_t * info)
92{
93        unsigned idx;
94        unsigned long sector_size = info->size / info->sector_count;
95
96        for (idx = 0; idx < info->sector_count; idx += 1) {
97                info->start[idx] = base + (idx * sector_size);
98        }
99}
100
101/*-----------------------------------------------------------------------
102 */
103void flash_print_info (flash_info_t * info)
104{
105        int i;
106        int k;
107        int size;
108        int erased;
109        volatile unsigned long *flash;
110
111        if (info->flash_id == FLASH_UNKNOWN) {
112                printf ("missing or unknown FLASH type\n");
113                return;
114        }
115
116        switch (info->flash_id & FLASH_VENDMASK) {
117        case FLASH_MAN_AMD:
118                printf ("AMD ");
119                break;
120        case FLASH_MAN_FUJ:
121                printf ("FUJITSU ");
122                break;
123        case FLASH_MAN_SST:
124                printf ("SST ");
125                break;
126        case FLASH_MAN_STM:
127                printf ("ST Micro ");
128                break;
129        default:
130                printf ("Unknown Vendor ");
131                break;
132        }
133
134          /* (Reduced table of only parts expected in JSE boards.) */
135        switch (info->flash_id) {
136        case FLASH_MAN_AMD | FLASH_AM040:
137                printf ("AM29F040 (512 Kbit, uniform sector size)\n");
138                break;
139        case FLASH_MAN_STM | FLASH_AM040:
140                printf ("MM29W040W (512 Kbit, uniform sector size)\n");
141                break;
142        default:
143                printf ("Unknown Chip Type\n");
144                break;
145        }
146
147        printf ("  Size: %ld KB in %d Sectors\n",
148                info->size >> 10, info->sector_count);
149
150        printf ("  Sector Start Addresses:");
151        for (i = 0; i < info->sector_count; ++i) {
152                /*
153                 * Check if whole sector is erased
154                 */
155                if (i != (info->sector_count - 1))
156                        size = info->start[i + 1] - info->start[i];
157                else
158                        size = info->start[0] + info->size - info->start[i];
159                erased = 1;
160                flash = (volatile unsigned long *) info->start[i];
161                size = size >> 2;       /* divide by 4 for longword access */
162                for (k = 0; k < size; k++) {
163                        if (*flash++ != 0xffffffff) {
164                                erased = 0;
165                                break;
166                        }
167                }
168
169                if ((i % 5) == 0)
170                        printf ("\n   ");
171                printf (" %08lX%s%s",
172                        info->start[i],
173                        erased ? " E" : "  ", info->protect[i] ? "RO " : "   "
174                );
175        }
176        printf ("\n");
177        return;
178}
179
180/*-----------------------------------------------------------------------
181 */
182
183
184/*-----------------------------------------------------------------------
185 */
186
187/*
188 * The following code cannot be run from FLASH!
189 */
190static ulong flash_get_size (vu_long * addr, flash_info_t * info)
191{
192        short i;
193        FLASH_WORD_SIZE value;
194        ulong base = (ulong) addr;
195        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *) addr;
196
197        /* Write auto select command: read Manufacturer ID */
198        addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
199        addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
200        addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00900090;
201
202        value = addr2[0];
203
204        switch (value) {
205        case (FLASH_WORD_SIZE) AMD_MANUFACT:
206                info->flash_id = FLASH_MAN_AMD;
207                break;
208        case (FLASH_WORD_SIZE) FUJ_MANUFACT:
209                info->flash_id = FLASH_MAN_FUJ;
210                break;
211        case (FLASH_WORD_SIZE) SST_MANUFACT:
212                info->flash_id = FLASH_MAN_SST;
213                break;
214        case (FLASH_WORD_SIZE)STM_MANUFACT:
215                info->flash_id = FLASH_MAN_STM;
216                break;
217        default:
218                info->flash_id = FLASH_UNKNOWN;
219                info->sector_count = 0;
220                info->size = 0;
221                printf("Unknown flash manufacturer code: 0x%x\n", value);
222                return (0);     /* no or unknown flash  */
223        }
224
225        value = addr2[1];       /* device ID            */
226
227        switch (value) {
228        case (FLASH_WORD_SIZE) AMD_ID_F040B:
229                info->flash_id += FLASH_AM040;
230                info->sector_count = 8;
231                info->size = 0x0080000; /* => 512 ko */
232                break;
233        case (FLASH_WORD_SIZE) AMD_ID_LV040B:
234                info->flash_id += FLASH_AM040;
235                info->sector_count = 8;
236                info->size = 0x0080000; /* => 512 ko */
237                break;
238        case (FLASH_WORD_SIZE)STM_ID_M29W040B: /* most likele JSE chip */
239                info->flash_id += FLASH_AM040;
240                info->sector_count = 8;
241                info->size = 0x0080000; /* => 512 ko */
242                break;
243        default:
244                info->flash_id = FLASH_UNKNOWN;
245                return (0);     /* => no or unknown flash */
246
247        }
248
249          /* Calculate the sector offsets (Use JSE Optimized code). */
250        flash_get_offsets(base, info);
251
252        /* check for protected sectors */
253        for (i = 0; i < info->sector_count; i++) {
254                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
255                /* D0 = 1 if protected */
256                addr2 = (volatile FLASH_WORD_SIZE *) (info->start[i]);
257                if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
258                        info->protect[i] = 0;
259                else
260                        info->protect[i] = addr2[2] & 1;
261        }
262
263        /*
264         * Prevent writes to uninitialized FLASH.
265         */
266        if (info->flash_id != FLASH_UNKNOWN) {
267                addr2 = (FLASH_WORD_SIZE *) info->start[0];
268                *addr2 = (FLASH_WORD_SIZE) 0x00F000F0;  /* reset bank */
269        }
270
271        return (info->size);
272}
273
274int wait_for_DQ7 (flash_info_t * info, int sect)
275{
276        ulong start, now, last;
277        volatile FLASH_WORD_SIZE *addr =
278                (FLASH_WORD_SIZE *) (info->start[sect]);
279
280        start = get_timer (0);
281        last = start;
282        while ((addr[0] & (FLASH_WORD_SIZE) 0x00800080) !=
283               (FLASH_WORD_SIZE) 0x00800080) {
284                if ((now = get_timer (start)) > CFG_FLASH_ERASE_TOUT) {
285                        printf ("Timeout\n");
286                        return -1;
287                }
288                /* show that we're waiting */
289                if ((now - last) > 1000) {      /* every second */
290                        putc ('.');
291                        last = now;
292                }
293        }
294        return 0;
295}
296
297/*-----------------------------------------------------------------------
298 */
299
300int flash_erase (flash_info_t * info, int s_first, int s_last)
301{
302        volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *) (info->start[0]);
303        volatile FLASH_WORD_SIZE *addr2;
304        int flag, prot, sect, l_sect;
305        int i;
306
307        if ((s_first < 0) || (s_first > s_last)) {
308                if (info->flash_id == FLASH_UNKNOWN) {
309                        printf ("- missing\n");
310                } else {
311                        printf ("- no sectors to erase\n");
312                }
313                return 1;
314        }
315
316        if (info->flash_id == FLASH_UNKNOWN) {
317                printf ("Can't erase unknown flash type - aborted\n");
318                return 1;
319        }
320
321        prot = 0;
322        for (sect = s_first; sect <= s_last; ++sect) {
323                if (info->protect[sect]) {
324                        prot++;
325                }
326        }
327
328        if (prot) {
329                printf ("- Warning: %d protected sectors will not be erased!\n", prot);
330        } else {
331                printf ("\n");
332        }
333
334        l_sect = -1;
335
336        /* Disable interrupts which might cause a timeout here */
337        flag = disable_interrupts ();
338
339        /* Start erase on unprotected sectors */
340        for (sect = s_first; sect <= s_last; sect++) {
341                if (info->protect[sect] == 0) { /* not protected */
342                        addr2 = (FLASH_WORD_SIZE *) (info->start[sect]);
343                        printf ("Erasing sector %p\n", addr2);  /* CLH */
344
345                        if ((info->flash_id & FLASH_VENDMASK) ==
346                            FLASH_MAN_SST) {
347                                addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
348                                addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
349                                addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
350                                addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
351                                addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
352                                addr2[0] = (FLASH_WORD_SIZE) 0x00500050;        /* block erase */
353                                for (i = 0; i < 50; i++)
354                                        udelay (1000);  /* wait 1 ms */
355                        } else {
356                                addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
357                                addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
358                                addr[ADDR0] = (FLASH_WORD_SIZE) 0x00800080;
359                                addr[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
360                                addr[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
361                                addr2[0] = (FLASH_WORD_SIZE) 0x00300030;        /* sector erase */
362                        }
363                        l_sect = sect;
364                        /*
365                         * Wait for each sector to complete, it's more
366                         * reliable.  According to AMD Spec, you must
367                         * issue all erase commands within a specified
368                         * timeout.  This has been seen to fail, especially
369                         * if printf()s are included (for debug)!!
370                         */
371                        wait_for_DQ7 (info, sect);
372                }
373        }
374
375        /* re-enable interrupts if necessary */
376        if (flag)
377                enable_interrupts ();
378
379        /* wait at least 80us - let's wait 1 ms */
380        udelay (1000);
381
382#if 0
383        /*
384         * We wait for the last triggered sector
385         */
386        if (l_sect < 0)
387                goto DONE;
388        wait_for_DQ7 (info, l_sect);
389
390DONE:
391#endif
392        /* reset to read mode */
393        addr = (FLASH_WORD_SIZE *) info->start[0];
394        addr[0] = (FLASH_WORD_SIZE) 0x00F000F0; /* reset bank */
395
396        printf (" done\n");
397        return 0;
398}
399
400/*-----------------------------------------------------------------------
401 * Copy memory to flash, returns:
402 * 0 - OK
403 * 1 - write timeout
404 * 2 - Flash not erased
405 */
406
407int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
408{
409        ulong cp, wp, data;
410        int i, l, rc;
411
412        wp = (addr & ~3);       /* get lower word aligned address */
413
414        /*
415         * handle unaligned start bytes
416         */
417        if ((l = addr - wp) != 0) {
418                data = 0;
419                for (i = 0, cp = wp; i < l; ++i, ++cp) {
420                        data = (data << 8) | (*(uchar *) cp);
421                }
422                for (; i < 4 && cnt > 0; ++i) {
423                        data = (data << 8) | *src++;
424                        --cnt;
425                        ++cp;
426                }
427                for (; cnt == 0 && i < 4; ++i, ++cp) {
428                        data = (data << 8) | (*(uchar *) cp);
429                }
430
431                if ((rc = write_word (info, wp, data)) != 0) {
432                        return (rc);
433                }
434                wp += 4;
435        }
436
437        /*
438         * handle word aligned part
439         */
440        while (cnt >= 4) {
441                data = 0;
442                for (i = 0; i < 4; ++i) {
443                        data = (data << 8) | *src++;
444                }
445                if ((rc = write_word (info, wp, data)) != 0) {
446                        return (rc);
447                }
448                wp += 4;
449                cnt -= 4;
450        }
451
452        if (cnt == 0) {
453                return (0);
454        }
455
456        /*
457         * handle unaligned tail bytes
458         */
459        data = 0;
460        for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
461                data = (data << 8) | *src++;
462                --cnt;
463        }
464        for (; i < 4; ++i, ++cp) {
465                data = (data << 8) | (*(uchar *) cp);
466        }
467
468        return (write_word (info, wp, data));
469}
470
471/*-----------------------------------------------------------------------
472 * Write a word to Flash, returns:
473 * 0 - OK
474 * 1 - write timeout
475 * 2 - Flash not erased
476 */
477static int write_word (flash_info_t * info, ulong dest, ulong data)
478{
479        volatile FLASH_WORD_SIZE *addr2 =
480                (FLASH_WORD_SIZE *) (info->start[0]);
481        volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *) dest;
482        volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *) & data;
483        ulong start;
484        int i;
485
486        /* Check if Flash is (sufficiently) erased */
487        if ((*((volatile FLASH_WORD_SIZE *) dest) &
488            (FLASH_WORD_SIZE) data) != (FLASH_WORD_SIZE) data) {
489                return (2);
490        }
491
492        for (i = 0; i < 4 / sizeof (FLASH_WORD_SIZE); i++) {
493                int flag;
494
495                /* Disable interrupts which might cause a timeout here */
496                flag = disable_interrupts ();
497
498                addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00AA00AA;
499                addr2[ADDR1] = (FLASH_WORD_SIZE) 0x00550055;
500                addr2[ADDR0] = (FLASH_WORD_SIZE) 0x00A000A0;
501
502                dest2[i] = data2[i];
503
504                /* re-enable interrupts if necessary */
505                if (flag)
506                        enable_interrupts ();
507
508                /* data polling for D7 */
509                start = get_timer (0);
510                while ((dest2[i] & (FLASH_WORD_SIZE) 0x00800080) !=
511                       (data2[i] & (FLASH_WORD_SIZE) 0x00800080)) {
512
513                        if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
514                                return (1);
515                        }
516                }
517        }
518
519        return (0);
520}
Note: See TracBrowser for help on using the repository browser.