source: SVN/rincon/u-boot/board/w7o/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: 23.7 KB
Line 
1/*
2 * (C) Copyright 2001
3 * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
4 *  Based on code by:
5 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26#include <common.h>
27#include <ppc4xx.h>
28#include <asm/processor.h>
29
30#include <watchdog.h>
31
32flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips    */
33
34/*-----------------------------------------------------------------------
35 * Functions
36 */
37static ulong flash_get_size (vu_long *addr, flash_info_t *info);
38static int write_word8(flash_info_t *info, ulong dest, ulong data);
39static int write_word32 (flash_info_t *info, ulong dest, ulong data);
40static void flash_get_offsets (ulong base, flash_info_t *info);
41
42/*-----------------------------------------------------------------------
43 */
44
45unsigned long flash_init (void)
46{
47    int i;
48    unsigned long size_b0, base_b0;
49    unsigned long size_b1, base_b1;
50
51    /* Init: no FLASHes known */
52    for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) {
53        flash_info[i].flash_id = FLASH_UNKNOWN;
54    }
55
56    /* Get Size of Boot and Main Flashes */
57    size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
58    if (flash_info[0].flash_id == FLASH_UNKNOWN) {
59        printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
60            size_b0, size_b0<<20);
61        return 0;
62    }
63    size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
64    if (flash_info[1].flash_id == FLASH_UNKNOWN) {
65        printf ("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
66            size_b1, size_b1<<20);
67        return 0;
68    }
69
70    /* Calculate base addresses */
71    base_b0 = -size_b0;
72    base_b1 = -size_b1;
73
74    /* Setup offsets for Boot Flash */
75    flash_get_offsets (base_b0, &flash_info[0]);
76
77    /* Protect board level data */
78    (void)flash_protect(FLAG_PROTECT_SET,
79                        base_b0,
80                        flash_info[0].start[1] - 1,
81                        &flash_info[0]);
82
83
84    /* Monitor protection ON by default */
85    (void)flash_protect(FLAG_PROTECT_SET,
86                        base_b0 + size_b0 - monitor_flash_len,
87                        base_b0 + size_b0 - 1,
88                        &flash_info[0]);
89
90    /* Protect the FPGA image */
91    (void)flash_protect(FLAG_PROTECT_SET,
92                        FLASH_BASE1_PRELIM,
93                        FLASH_BASE1_PRELIM + CFG_FPGA_IMAGE_LEN - 1,
94                        &flash_info[1]);
95
96    /* Protect the default boot image */
97    (void)flash_protect(FLAG_PROTECT_SET,
98                        FLASH_BASE1_PRELIM + CFG_FPGA_IMAGE_LEN,
99                        FLASH_BASE1_PRELIM + CFG_FPGA_IMAGE_LEN + 0x600000 - 1,
100                        &flash_info[1]);
101
102    /* Setup offsets for Main Flash */
103    flash_get_offsets (FLASH_BASE1_PRELIM, &flash_info[1]);
104
105    return (size_b0 + size_b1);
106} /* end flash_init() */
107
108/*-----------------------------------------------------------------------
109 */
110static void flash_get_offsets (ulong base, flash_info_t *info)
111{
112    int i;
113
114    /* set up sector start address table - FOR BOOT ROM ONLY!!! */
115    if ((info->flash_id & FLASH_TYPEMASK)  == FLASH_AM040) {
116        for (i = 0; i < info->sector_count; i++)
117            info->start[i] = base + (i * 0x00010000);
118    }
119} /* end flash_get_offsets() */
120
121/*-----------------------------------------------------------------------
122 */
123void flash_print_info  (flash_info_t *info)
124{
125    int i;
126    int k;
127    int size;
128    int erased;
129    volatile unsigned long *flash;
130
131    if (info->flash_id == FLASH_UNKNOWN) {
132        printf ("missing or unknown FLASH type\n");
133        return;
134    }
135
136    switch (info->flash_id & FLASH_VENDMASK) {
137        case FLASH_MAN_AMD:     printf ("1 x AMD ");    break;
138        case FLASH_MAN_STM:     printf ("1 x STM ");    break;
139        case FLASH_MAN_INTEL:   printf ("2 x Intel ");  break;
140        default:                printf ("Unknown Vendor ");
141    }
142
143    switch (info->flash_id & FLASH_TYPEMASK) {
144        case FLASH_AM040:
145            if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
146                printf ("AM29LV040 (4096 Kbit, uniform sector size)\n");
147            else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM)
148                printf ("M29W040B (4096 Kbit, uniform block size)\n");
149            else
150                printf ("UNKNOWN 29x040x (4096 Kbit, uniform sector size)\n");
151            break;
152        case FLASH_28F320J3A:
153            printf ("28F320J3A (32 Mbit = 128K x 32)\n");
154            break;
155        case FLASH_28F640J3A:
156            printf ("28F640J3A (64 Mbit = 128K x 64)\n");
157            break;
158        case FLASH_28F128J3A:
159            printf ("28F128J3A (128 Mbit = 128K x 128)\n");
160            break;
161        default:
162            printf ("Unknown Chip Type\n");
163    }
164
165    if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM) {
166        printf ("  Size: %ld KB in %d Blocks\n",
167                info->size >> 10, info->sector_count);
168    } else {
169        printf ("  Size: %ld KB in %d Sectors\n",
170                info->size >> 10, info->sector_count);
171    }
172
173    printf ("  Sector Start Addresses:");
174    for (i=0; i<info->sector_count; ++i) {
175        /*
176         * Check if whole sector is erased
177         */
178        if (i != (info->sector_count-1))
179            size = info->start[i+1] - info->start[i];
180        else
181            size = info->start[0] + info->size - info->start[i];
182        erased = 1;
183        flash = (volatile unsigned long *)info->start[i];
184        size = size >> 2;        /* divide by 4 for longword access */
185        for (k=0; k<size; k++)
186        {
187            if (*flash++ != 0xffffffff)
188            {
189                erased = 0;
190                break;
191            }
192        }
193
194        if ((i % 5) == 0)
195            printf ("\n   ");
196        printf (" %08lX%s%s",
197            info->start[i],
198            erased ? " E" : "  ",
199            info->protect[i] ? "RO " : "   "
200        );
201    }
202    printf ("\n");
203} /* end flash_print_info() */
204
205/*
206 * The following code cannot be run from FLASH!
207 */
208static ulong flash_get_size (vu_long *addr, flash_info_t *info)
209{
210    short i;
211    ulong base = (ulong)addr;
212
213    /* Setup default type */
214    info->flash_id = FLASH_UNKNOWN;
215    info->sector_count =0;
216    info->size = 0;
217
218    /* Test for Boot Flash */
219    if (base == FLASH_BASE0_PRELIM) {
220        unsigned char value;
221        volatile unsigned char * addr2 = (unsigned char *)addr;
222
223        /* Write auto select command: read Manufacturer ID */
224        *(addr2 + 0x555) = 0xaa;
225        *(addr2 + 0x2aa) = 0x55;
226        *(addr2 + 0x555) = 0x90;
227
228        /* Manufacture ID */
229        value = *addr2;
230        switch (value) {
231            case (unsigned char)AMD_MANUFACT:
232                info->flash_id = FLASH_MAN_AMD;
233                break;
234            case (unsigned char)STM_MANUFACT:
235                info->flash_id = FLASH_MAN_STM;
236                break;
237            default:
238                *addr2 = 0xf0;              /* no or unknown flash  */
239                return 0;
240        }
241
242        /* Device ID */
243        value = *(addr2 + 1);
244        switch (value) {
245            case (unsigned char)AMD_ID_LV040B:
246            case (unsigned char)STM_ID_29W040B:
247                info->flash_id += FLASH_AM040;
248                info->sector_count = 8;
249                info->size = 0x00080000;
250                break;                       /* => 512Kb */
251            default:
252                *addr2 = 0xf0;               /* => no or unknown flash */
253                return 0;
254        }
255    }
256    else { /* MAIN Flash */
257        unsigned long value;
258        volatile unsigned long * addr2 = (unsigned long *)addr;
259
260        /* Write auto select command: read Manufacturer ID */
261        *addr2 = 0x90909090;
262
263        /* Manufacture ID */
264        value = *addr2;
265        switch (value) {
266            case (unsigned long)INTEL_MANUFACT:
267                info->flash_id = FLASH_MAN_INTEL;
268                break;
269            default:
270                *addr2 = 0xff;              /* no or unknown flash  */
271                return 0;
272        }
273
274        /* Device ID - This shit is interleaved... */
275        value = *(addr2 + 1);
276        switch (value) {
277            case (unsigned long)INTEL_ID_28F320J3A:
278                info->flash_id += FLASH_28F320J3A;
279                info->sector_count = 32;
280                info->size = 0x00400000 * 2;
281                break;                       /* => 2 X 4 MB */
282            case (unsigned long)INTEL_ID_28F640J3A:
283                info->flash_id += FLASH_28F640J3A;
284                info->sector_count = 64;
285                info->size = 0x00800000 * 2;
286                break;                       /* => 2 X 8 MB */
287            case (unsigned long)INTEL_ID_28F128J3A:
288                info->flash_id += FLASH_28F128J3A;
289                info->sector_count = 128;
290                info->size = 0x01000000 * 2;
291                break;                       /* => 2 X 16 MB */
292            default:
293                *addr2 = 0xff;               /* => no or unknown flash */
294        }
295    }
296
297    /* Make sure we don't exceed CFG_MAX_FLASH_SECT */
298    if (info->sector_count > CFG_MAX_FLASH_SECT) {
299        printf ("** ERROR: sector count %d > max (%d) **\n",
300                info->sector_count, CFG_MAX_FLASH_SECT);
301        info->sector_count = CFG_MAX_FLASH_SECT;
302    }
303
304    /* set up sector start address table */
305    switch (info->flash_id & FLASH_TYPEMASK) {
306        case FLASH_AM040:
307            for (i = 0; i < info->sector_count; i++)
308                info->start[i] = base + (i * 0x00010000);
309            break;
310        case FLASH_28F320J3A:
311        case FLASH_28F640J3A:
312        case FLASH_28F128J3A:
313            for (i = 0; i < info->sector_count; i++)
314                info->start[i] = base + (i * 0x00020000 * 2); /* 2 Banks */
315            break;
316    }
317
318    /* Test for Boot Flash */
319    if (base == FLASH_BASE0_PRELIM) {
320        volatile unsigned char *addr2;
321        /* check for protected sectors */
322        for (i = 0; i < info->sector_count; i++) {
323            /* read sector protection at sector address, (AX .. A0) = 0x02 */
324            /* D0 = 1 if protected */
325            addr2 = (volatile unsigned char *)(info->start[i]);
326            info->protect[i] = *(addr2 + 2) & 1;
327        }
328
329        /* Restore read mode */
330        *(unsigned char *)base = 0xF0;       /* Reset NORMAL Flash */
331    }
332    else { /* Main Flash */
333        volatile unsigned long *addr2;
334        /* check for protected sectors */
335        for (i = 0; i < info->sector_count; i++) {
336            /* read sector protection at sector address, (AX .. A0) = 0x02 */
337            /* D0 = 1 if protected */
338            addr2 = (volatile unsigned long *)(info->start[i]);
339            info->protect[i] = *(addr2 + 2) & 0x1;
340        }
341
342        /* Restore read mode */
343        *(unsigned long *)base = 0xFFFFFFFF; /* Reset  Flash */
344    }
345
346    return (info->size);
347} /* end flash_get_size() */
348
349/*-----------------------------------------------------------------------
350 */
351
352static int wait_for_DQ7(ulong addr, uchar cmp_val, ulong tout)
353{
354    int i;
355
356    volatile uchar *vaddr =  (uchar *)addr;
357
358    /* Loop X times */
359    for (i = 1; i <= (100 * tout); i++) {    /* Wait up to tout ms */
360        udelay(10);
361        /* Pause 10 us */
362
363        /* Check for completion */
364        if ((vaddr[0] & 0x80) == (cmp_val & 0x80)) {
365            return 0;
366        }
367
368        /* KEEP THE LUSER HAPPY - Print a dot every 1.1 seconds */
369        if (!(i % 110000))
370            putc('.');
371
372        /* Kick the dog if needed */
373        WATCHDOG_RESET();
374    }
375
376    return 1;
377} /* wait_for_DQ7() */
378
379/*-----------------------------------------------------------------------
380 */
381
382static int flash_erase8(flash_info_t *info, int s_first, int s_last)
383{
384    int tcode, rcode = 0;
385    volatile uchar *addr = (uchar *)(info->start[0]);
386    volatile uchar *sector_addr;
387    int flag, prot, sect;
388
389    /* Validate arguments */
390    if ((s_first < 0) || (s_first > s_last)) {
391        if (info->flash_id == FLASH_UNKNOWN)
392            printf ("- missing\n");
393        else
394            printf ("- no sectors to erase\n");
395        return 1;
396    }
397
398    /* Check for KNOWN flash type */
399    if (info->flash_id == FLASH_UNKNOWN) {
400        printf ("Can't erase unknown flash type - aborted\n");
401        return 1;
402    }
403
404    /* Check for protected sectors */
405    prot = 0;
406    for (sect = s_first; sect <= s_last; ++sect) {
407        if (info->protect[sect])
408            prot++;
409    }
410    if (prot)
411        printf ("- Warning: %d protected sectors will not be erased!\n", prot);
412    else
413        printf ("\n");
414
415    /* Start erase on unprotected sectors */
416    for (sect = s_first; sect <= s_last; sect++) {
417        if (info->protect[sect] == 0) {      /* not protected */
418            sector_addr = (uchar *)(info->start[sect]);
419
420                if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM)
421                    printf("Erasing block %p\n", sector_addr);
422                else
423                    printf("Erasing sector %p\n", sector_addr);
424
425            /* Disable interrupts which might cause Flash to timeout */
426            flag = disable_interrupts();
427
428            *(addr + 0x555) = (uchar)0xAA;
429            *(addr + 0x2aa) = (uchar)0x55;
430            *(addr + 0x555) = (uchar)0x80;
431            *(addr + 0x555) = (uchar)0xAA;
432            *(addr + 0x2aa) = (uchar)0x55;
433            *sector_addr = (uchar)0x30;      /* sector erase */
434
435            /*
436             * Wait for each sector to complete, it's more
437             * reliable.  According to AMD Spec, you must
438             * issue all erase commands within a specified
439             * timeout.  This has been seen to fail, especially
440             * if printf()s are included (for debug)!!
441             * Takes up to 6 seconds.
442             */
443            tcode  = wait_for_DQ7((ulong)sector_addr, 0x80, 6000);
444
445            /* re-enable interrupts if necessary */
446            if (flag)
447                enable_interrupts();
448
449            /* Make sure we didn't timeout */
450            if (tcode) {
451                printf ("Timeout\n");
452                rcode = 1;
453            }
454        }
455    }
456
457    /* wait at least 80us - let's wait 1 ms */
458    udelay (1000);
459
460    /* reset to read mode */
461    addr = (uchar *)info->start[0];
462    *addr = (uchar)0xF0;                     /* reset bank */
463
464    printf (" done\n");
465    return rcode;
466} /* end flash_erase8() */
467
468static int flash_erase32(flash_info_t *info, int s_first, int s_last)
469{
470    int flag, sect;
471    ulong start, now, last;
472    int prot = 0;
473
474    /* Validate arguments */
475    if ((s_first < 0) || (s_first > s_last)) {
476        if (info->flash_id == FLASH_UNKNOWN)
477            printf ("- missing\n");
478        else
479            printf ("- no sectors to erase\n");
480        return 1;
481    }
482
483    /* Check for KNOWN flash type */
484    if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) {
485        printf ("Can erase only Intel flash types - aborted\n");
486        return 1;
487    }
488
489    /* Check for protected sectors */
490    for (sect = s_first; sect <= s_last; ++sect) {
491        if (info->protect[sect])
492            prot++;
493    }
494    if (prot)
495        printf ("- Warning: %d protected sectors will not be erased!\n", prot);
496    else
497        printf ("\n");
498
499    start = get_timer (0);
500    last  = start;
501    /* Start erase on unprotected sectors */
502    for (sect = s_first; sect <= s_last; sect++) {
503        WATCHDOG_RESET();
504        if (info->protect[sect] == 0) {      /* not protected */
505            vu_long *addr = (vu_long *)(info->start[sect]);
506            unsigned long status;
507
508            /* Disable interrupts which might cause a timeout here */
509            flag = disable_interrupts();
510
511            *addr = 0x00500050;              /* clear status register */
512            *addr = 0x00200020;              /* erase setup */
513            *addr = 0x00D000D0;              /* erase confirm */
514
515            /* re-enable interrupts if necessary */
516            if (flag)
517                enable_interrupts();
518
519            /* Wait at least 80us - let's wait 1 ms */
520            udelay (1000);
521
522            while (((status = *addr) & 0x00800080) != 0x00800080) {
523                if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
524                    printf ("Timeout\n");
525                    *addr = 0x00B000B0;      /* suspend erase      */
526                    *addr = 0x00FF00FF;      /* reset to read mode */
527                    return 1;
528                }
529
530                /* show that we're waiting */
531                if ((now - last) > 990) {   /* every second */
532                    putc ('.');
533                    last = now;
534                }
535            }
536            *addr = 0x00FF00FF;              /* reset to read mode */
537        }
538    }
539    printf (" done\n");
540    return 0;
541} /* end flash_erase32() */
542
543int flash_erase(flash_info_t *info, int s_first, int s_last)
544{
545    if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040)
546        return flash_erase8(info, s_first, s_last);
547    else
548        return flash_erase32(info, s_first, s_last);
549} /* end flash_erase() */
550
551/*-----------------------------------------------------------------------
552 * Copy memory to flash, returns:
553 * 0 - OK
554 * 1 - write timeout
555 * 2 - Flash not erased
556 */
557static int write_buff8(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
558{
559    ulong cp, wp, data;
560    ulong start;
561    int i, l, rc;
562
563    start = get_timer (0);
564
565    wp = (addr & ~3);                        /* get lower word
566                                                aligned address */
567
568    /*
569     * handle unaligned start bytes
570     */
571    if ((l = addr - wp) != 0) {
572        data = 0;
573        for (i=0, cp=wp; i<l; ++i, ++cp) {
574            data = (data << 8) | (*(uchar *)cp);
575        }
576        for (; i<4 && cnt>0; ++i) {
577            data = (data << 8) | *src++;
578            --cnt;
579            ++cp;
580        }
581        for (; cnt==0 && i<4; ++i, ++cp) {
582            data = (data << 8) | (*(uchar *)cp);
583        }
584
585        if ((rc = write_word8(info, wp, data)) != 0) {
586            return (rc);
587        }
588        wp += 4;
589    }
590
591    /*
592     * handle word aligned part
593     */
594    while (cnt >= 4) {
595        data = 0;
596        for (i=0; i<4; ++i) {
597            data = (data << 8) | *src++;
598        }
599        if ((rc = write_word8(info, wp, data)) != 0) {
600            return (rc);
601        }
602        wp  += 4;
603        cnt -= 4;
604        if (get_timer(start) > 1000) {   /* every second */
605           WATCHDOG_RESET();
606           putc ('.');
607           start = get_timer(0);
608        }
609    }
610
611    if (cnt == 0) {
612        return (0);
613    }
614
615    /*
616     * handle unaligned tail bytes
617     */
618    data = 0;
619    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
620        data = (data << 8) | *src++;
621        --cnt;
622    }
623    for (; i<4; ++i, ++cp) {
624        data = (data << 8) | (*(uchar *)cp);
625    }
626
627    return (write_word8(info, wp, data));
628} /* end write_buff8() */
629
630#define FLASH_WIDTH     4       /* flash bus width in bytes */
631static int write_buff32 (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
632{
633        ulong cp, wp, data;
634        int i, l, rc;
635        ulong start;
636
637        start = get_timer (0);
638
639        if (info->flash_id == FLASH_UNKNOWN) {
640                return 4;
641        }
642
643        wp = (addr & ~(FLASH_WIDTH-1)); /* get lower FLASH_WIDTH aligned address */
644
645        /*
646         * handle unaligned start bytes
647         */
648        if ((l = addr - wp) != 0) {
649                data = 0;
650                for (i=0, cp=wp; i<l; ++i, ++cp) {
651                        data = (data << 8) | (*(uchar *)cp);
652                }
653                for (; i<FLASH_WIDTH && cnt>0; ++i) {
654                        data = (data << 8) | *src++;
655                        --cnt;
656                        ++cp;
657                }
658                for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) {
659                        data = (data << 8) | (*(uchar *)cp);
660                }
661
662                if ((rc = write_word32(info, wp, data)) != 0) {
663                        return (rc);
664                }
665                wp += FLASH_WIDTH;
666        }
667
668        /*
669         * handle FLASH_WIDTH aligned part
670         */
671        while (cnt >= FLASH_WIDTH) {
672                data = 0;
673                for (i=0; i<FLASH_WIDTH; ++i) {
674                        data = (data << 8) | *src++;
675                }
676                if ((rc = write_word32(info, wp, data)) != 0) {
677                        return (rc);
678                }
679                wp  += FLASH_WIDTH;
680                cnt -= FLASH_WIDTH;
681          if (get_timer(start) > 990) {   /* every second */
682                        putc ('.');
683                        start = get_timer(0);
684                }
685        }
686
687        if (cnt == 0) {
688                return (0);
689        }
690
691        /*
692         * handle unaligned tail bytes
693         */
694        data = 0;
695        for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) {
696                data = (data << 8) | *src++;
697                --cnt;
698        }
699        for (; i<FLASH_WIDTH; ++i, ++cp) {
700                data = (data << 8) | (*(uchar *)cp);
701        }
702
703        return (write_word32(info, wp, data));
704} /* write_buff32() */
705
706int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
707{
708    int retval;
709
710    if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040)
711        retval = write_buff8(info, src, addr, cnt);
712    else
713        retval = write_buff32(info, src, addr, cnt);
714
715    return retval;
716} /* end write_buff() */
717
718/*-----------------------------------------------------------------------
719 * Write a word to Flash, returns:
720 * 0 - OK
721 * 1 - write timeout
722 * 2 - Flash not erased
723 */
724
725static int write_word8(flash_info_t *info, ulong dest, ulong data)
726{
727    volatile uchar *addr2 = (uchar *)(info->start[0]);
728    volatile uchar *dest2 = (uchar *)dest;
729    volatile uchar *data2 = (uchar *)&data;
730    int flag;
731    int i, tcode, rcode = 0;
732
733    /* Check if Flash is (sufficently) erased */
734    if ((*((volatile uchar *)dest) &
735        (uchar)data) != (uchar)data) {
736        return (2);
737    }
738
739    for (i=0; i < (4 / sizeof(uchar)); i++) {
740        /* Disable interrupts which might cause a timeout here */
741        flag = disable_interrupts();
742
743        *(addr2 + 0x555) = (uchar)0xAA;
744        *(addr2 + 0x2aa) = (uchar)0x55;
745        *(addr2 + 0x555) = (uchar)0xA0;
746
747        dest2[i] = data2[i];
748
749        /* Wait for write to complete, up to 1ms */
750        tcode = wait_for_DQ7((ulong)&dest2[i], data2[i], 1);
751
752        /* re-enable interrupts if necessary */
753        if (flag)
754            enable_interrupts();
755
756        /* Make sure we didn't timeout */
757        if (tcode) {
758            rcode = 1;
759        }
760    }
761
762    return rcode;
763} /* end write_word8() */
764
765static int write_word32(flash_info_t *info, ulong dest, ulong data)
766{
767    vu_long *addr = (vu_long *)dest;
768    ulong status;
769    ulong start;
770    int flag;
771
772    /* Check if Flash is (sufficiently) erased */
773    if ((*addr & data) != data) {
774        return (2);
775    }
776    /* Disable interrupts which might cause a timeout here */
777    flag = disable_interrupts();
778
779    *addr = 0x00400040;                      /* write setup */
780    *addr = data;
781
782    /* re-enable interrupts if necessary */
783    if (flag)
784        enable_interrupts();
785
786    start = get_timer (0);
787
788    while (((status = *addr) & 0x00800080) != 0x00800080) {
789        WATCHDOG_RESET();
790        if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
791            *addr = 0x00FF00FF;              /* restore read mode */
792            return (1);
793        }
794    }
795
796    *addr = 0x00FF00FF;                      /* restore read mode */
797
798    return (0);
799} /* end write_word32() */
800
801
802static int _flash_protect(flash_info_t *info, long sector)
803{
804    int i;
805    int flag;
806    ulong status;
807    int rcode = 0;
808    volatile long *addr = (long *)sector;
809
810    switch(info->flash_id & FLASH_TYPEMASK) {
811        case FLASH_28F320J3A:
812        case FLASH_28F640J3A:
813        case FLASH_28F128J3A:
814            /* Disable interrupts which might cause Flash to timeout */
815            flag = disable_interrupts();
816
817            /* Issue command */
818            *addr = 0x00500050L;             /* Clear the status register */
819            *addr = 0x00600060L;             /* Set lock bit setup */
820            *addr = 0x00010001L;             /* Set lock bit confirm */
821
822            /* Wait for command completion */
823            for (i = 0; i < 10; i++) {       /* 75us timeout, wait 100us */
824                udelay(10);
825                if ((*addr & 0x00800080L) == 0x00800080L)
826                    break;
827            }
828
829            /* Not successful? */
830            status = *addr;
831            if (status != 0x00800080L) {
832                printf("Protect %x sector failed: %x\n",
833                       (uint)sector, (uint)status);
834                rcode = 1;
835            }
836
837            /* Restore read mode */
838            *addr = 0x00ff00ffL;
839
840            /* re-enable interrupts if necessary */
841            if (flag)
842                enable_interrupts();
843
844            break;
845        case FLASH_AM040:                    /* No soft sector protection */
846            break;
847    }
848
849    /* Turn protection on for this sector */
850    for (i = 0; i < info->sector_count; i++) {
851        if (info->start[i] == sector) {
852            info->protect[i] = 1;
853            break;
854        }
855    }
856
857    return rcode;
858} /* end _flash_protect() */
859
860static int _flash_unprotect(flash_info_t *info, long sector)
861{
862    int i;
863    int flag;
864    ulong status;
865    int rcode = 0;
866    volatile long *addr = (long *)sector;
867
868    switch(info->flash_id & FLASH_TYPEMASK) {
869        case FLASH_28F320J3A:
870        case FLASH_28F640J3A:
871        case FLASH_28F128J3A:
872            /* Disable interrupts which might cause Flash to timeout */
873            flag = disable_interrupts();
874
875            *addr = 0x00500050L;             /* Clear the status register */
876            *addr = 0x00600060L;             /* Clear lock bit setup */
877            *addr = 0x00D000D0L;             /* Clear lock bit confirm */
878
879            /* Wait for command completion */
880            for (i = 0; i < 80 ; i++) {      /* 700ms timeout, wait 800 */
881                udelay(10000);               /* Delay 10ms */
882                if ((*addr & 0x00800080L) == 0x00800080L)
883                    break;
884            }
885
886            /* Not successful? */
887            status = *addr;
888            if (status != 0x00800080L) {
889                printf("Un-protect %x sector failed: %x\n",
890                       (uint)sector, (uint)status);
891                *addr = 0x00ff00ffL;
892                rcode = 1;
893            }
894
895            /* restore read mode */
896            *addr = 0x00ff00ffL;
897
898            /* re-enable interrupts if necessary */
899            if (flag)
900                enable_interrupts();
901
902            break;
903        case FLASH_AM040:                    /* No soft sector protection */
904            break;
905    }
906
907    /*
908     * Fix Intel's little red wagon.  Reprotect
909     * sectors that were protected before we undid
910     * protection on a specific sector.
911     */
912    for (i = 0; i < info->sector_count; i++) {
913        if (info->start[i] != sector) {
914            if (info->protect[i]) {
915                if (_flash_protect(info, info->start[i]))
916                    rcode = 1;
917            }
918        }
919        else /* Turn protection off for this sector */
920            info->protect[i] = 0;
921    }
922
923    return rcode;
924} /* end _flash_unprotect() */
925
926
927int flash_real_protect(flash_info_t *info, long sector, int prot)
928{
929    int rcode;
930
931    if (prot)
932        rcode = _flash_protect(info, info->start[sector]);
933    else
934        rcode = _flash_unprotect(info, info->start[sector]);
935
936    return rcode;
937} /* end flash_real_protect() */
938
939/*-----------------------------------------------------------------------
940 */
Note: See TracBrowser for help on using the repository browser.