source: SVN/rincon/u-boot/board/mx1fs2/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: 21.0 KB
Line 
1/*
2 * (C) 2000-2004 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
3 * (C) 2003 August Hoeraendl, Logotronic GmbH
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#undef CONFIG_FLASH_16BIT
25
26#include <common.h>
27
28#define FLASH_BANK_SIZE MX1FS2_FLASH_BANK_SIZE
29#define MAIN_SECT_SIZE  MX1FS2_FLASH_SECT_SIZE
30
31flash_info_t flash_info[CFG_MAX_FLASH_BANKS];   /* info for FLASH chips   */
32
33/*
34 * NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
35 *        has nothing to do with the flash chip being 8-bit or 16-bit.
36 */
37#ifdef CONFIG_FLASH_16BIT
38typedef unsigned short FLASH_PORT_WIDTH;
39typedef volatile unsigned short FLASH_PORT_WIDTHV;
40
41#define FLASH_ID_MASK   0xFFFF
42#else
43typedef unsigned long FLASH_PORT_WIDTH;
44typedef volatile unsigned long FLASH_PORT_WIDTHV;
45
46#define FLASH_ID_MASK   0xFFFFFFFF
47#endif
48
49#define FPW     FLASH_PORT_WIDTH
50#define FPWV    FLASH_PORT_WIDTHV
51
52#define ORMASK(size) ((-size) & OR_AM_MSK)
53
54/*-----------------------------------------------------------------------
55 * Functions
56 */
57#if 0
58static ulong flash_get_size(FPWV * addr, flash_info_t * info);
59static void flash_get_offsets(ulong base, flash_info_t * info);
60#endif
61static void flash_reset(flash_info_t * info);
62static int write_word_intel(flash_info_t * info, FPWV * dest, FPW data);
63static int write_word_amd(flash_info_t * info, FPWV * dest, FPW data);
64#define write_word(in, de, da)   write_word_amd(in, de, da)
65#ifdef CFG_FLASH_PROTECTION
66static void flash_sync_real_protect(flash_info_t * info);
67#endif
68
69/*-----------------------------------------------------------------------
70 * flash_init()
71 *
72 * sets up flash_info and returns size of FLASH (bytes)
73 */
74ulong
75flash_init(void)
76{
77        int i, j;
78        ulong size = 0;
79
80        for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
81                ulong flashbase = 0;
82                flash_info[i].flash_id =
83                    (FLASH_MAN_AMD & FLASH_VENDMASK) |
84                    (FLASH_AM640U & FLASH_TYPEMASK);
85                flash_info[i].size = FLASH_BANK_SIZE;
86                flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
87                memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
88                switch (i) {
89                case 0:
90                        flashbase = MX1FS2_FLASH_BASE;
91                        break;
92                default:
93                        panic("configured too many flash banks!\n");
94                        break;
95                }
96                for (j = 0; j < flash_info[i].sector_count; j++) {
97                        flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE;
98                }
99                size += flash_info[i].size;
100        }
101
102        /* Protect monitor and environment sectors */
103        flash_protect(FLAG_PROTECT_SET,
104                      CFG_FLASH_BASE,
105                      CFG_FLASH_BASE + _bss_start - _armboot_start,
106                      &flash_info[0]);
107
108        flash_protect(FLAG_PROTECT_SET,
109                      CONFIG_ENV_ADDR,
110                      CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
111
112        return size;
113}
114
115/*-----------------------------------------------------------------------
116 */
117static void
118flash_reset(flash_info_t * info)
119{
120        FPWV *base = (FPWV *) (info->start[0]);
121
122        /* Put FLASH back in read mode */
123        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
124                *base = (FPW) 0x00FF00FF;       /* Intel Read Mode */
125        else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
126                *base = (FPW) 0x00F000F0;       /* AMD Read Mode */
127}
128
129/*-----------------------------------------------------------------------
130 */
131#if 0
132static void
133flash_get_offsets(ulong base, flash_info_t * info)
134{
135        int i;
136
137        /* set up sector start address table */
138        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL
139            && (info->flash_id & FLASH_BTYPE)) {
140                int bootsect_size;      /* number of bytes/boot sector  */
141                int sect_size;  /* number of bytes/regular sector */
142
143                bootsect_size = 0x00002000 * (sizeof (FPW) / 2);
144                sect_size = 0x00010000 * (sizeof (FPW) / 2);
145
146                /* set sector offsets for bottom boot block type        */
147                for (i = 0; i < 8; ++i) {
148                        info->start[i] = base + (i * bootsect_size);
149                }
150                for (i = 8; i < info->sector_count; i++) {
151                        info->start[i] = base + ((i - 7) * sect_size);
152                }
153        } else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
154                   && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) {
155
156                int sect_size;  /* number of bytes/sector */
157
158                sect_size = 0x00010000 * (sizeof (FPW) / 2);
159
160                /* set up sector start address table (uniform sector type) */
161                for (i = 0; i < info->sector_count; i++)
162                        info->start[i] = base + (i * sect_size);
163        }
164}
165#endif /* 0 */
166
167/*-----------------------------------------------------------------------
168 */
169
170void
171flash_print_info(flash_info_t * info)
172{
173        int i;
174        uchar *boottype;
175        uchar *bootletter;
176        char *fmt;
177        uchar botbootletter[] = "B";
178        uchar topbootletter[] = "T";
179        uchar botboottype[] = "bottom boot sector";
180        uchar topboottype[] = "top boot sector";
181
182        if (info->flash_id == FLASH_UNKNOWN) {
183                printf("missing or unknown FLASH type\n");
184                return;
185        }
186
187        switch (info->flash_id & FLASH_VENDMASK) {
188        case FLASH_MAN_AMD:
189                printf("AMD ");
190                break;
191        case FLASH_MAN_BM:
192                printf("BRIGHT MICRO ");
193                break;
194        case FLASH_MAN_FUJ:
195                printf("FUJITSU ");
196                break;
197        case FLASH_MAN_SST:
198                printf("SST ");
199                break;
200        case FLASH_MAN_STM:
201                printf("STM ");
202                break;
203        case FLASH_MAN_INTEL:
204                printf("INTEL ");
205                break;
206        default:
207                printf("Unknown Vendor ");
208                break;
209        }
210
211        /* check for top or bottom boot, if it applies */
212        if (info->flash_id & FLASH_BTYPE) {
213                boottype = botboottype;
214                bootletter = botbootletter;
215        } else {
216                boottype = topboottype;
217                bootletter = topbootletter;
218        }
219
220        switch (info->flash_id & FLASH_TYPEMASK) {
221        case FLASH_AM640U:
222                fmt = "29LV641D (64 Mbit, uniform sectors)\n";
223                break;
224        case FLASH_28F800C3B:
225        case FLASH_28F800C3T:
226                fmt = "28F800C3%s (8 Mbit, %s)\n";
227                break;
228        case FLASH_INTEL800B:
229        case FLASH_INTEL800T:
230                fmt = "28F800B3%s (8 Mbit, %s)\n";
231                break;
232        case FLASH_28F160C3B:
233        case FLASH_28F160C3T:
234                fmt = "28F160C3%s (16 Mbit, %s)\n";
235                break;
236        case FLASH_INTEL160B:
237        case FLASH_INTEL160T:
238                fmt = "28F160B3%s (16 Mbit, %s)\n";
239                break;
240        case FLASH_28F320C3B:
241        case FLASH_28F320C3T:
242                fmt = "28F320C3%s (32 Mbit, %s)\n";
243                break;
244        case FLASH_INTEL320B:
245        case FLASH_INTEL320T:
246                fmt = "28F320B3%s (32 Mbit, %s)\n";
247                break;
248        case FLASH_28F640C3B:
249        case FLASH_28F640C3T:
250                fmt = "28F640C3%s (64 Mbit, %s)\n";
251                break;
252        case FLASH_INTEL640B:
253        case FLASH_INTEL640T:
254                fmt = "28F640B3%s (64 Mbit, %s)\n";
255                break;
256        default:
257                fmt = "Unknown Chip Type\n";
258                break;
259        }
260
261        printf(fmt, bootletter, boottype);
262
263        printf("  Size: %ld MB in %d Sectors\n",
264               info->size >> 20, info->sector_count);
265
266        printf("  Sector Start Addresses:");
267
268        for (i = 0; i < info->sector_count; ++i) {
269                if ((i % 5) == 0) {
270                        printf("\n   ");
271                }
272
273                printf(" %08lX%s", info->start[i],
274                       info->protect[i] ? " (RO)" : "     ");
275        }
276
277        printf("\n");
278}
279
280/*-----------------------------------------------------------------------
281 */
282
283/*
284 * The following code cannot be run from FLASH!
285 */
286
287#if 0
288ulong
289flash_get_size(FPWV * addr, flash_info_t * info)
290{
291        /* Write auto select command: read Manufacturer ID */
292
293        /* Write auto select command sequence and test FLASH answer */
294        addr[0x0555] = (FPW) 0x00AA00AA;        /* for AMD, Intel ignores this */
295        addr[0x02AA] = (FPW) 0x00550055;        /* for AMD, Intel ignores this */
296        addr[0x0555] = (FPW) 0x00900090;        /* selects Intel or AMD */
297
298        /* The manufacturer codes are only 1 byte, so just use 1 byte.
299         * This works for any bus width and any FLASH device width.
300         */
301        switch (addr[0] & 0xff) {
302
303        case (uchar) AMD_MANUFACT:
304                info->flash_id = FLASH_MAN_AMD;
305                break;
306
307        case (uchar) INTEL_MANUFACT:
308                info->flash_id = FLASH_MAN_INTEL;
309                break;
310
311        default:
312                info->flash_id = FLASH_UNKNOWN;
313                info->sector_count = 0;
314                info->size = 0;
315                break;
316        }
317
318        /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
319        if (info->flash_id != FLASH_UNKNOWN)
320                switch (addr[1]) {
321
322                case (FPW) AMD_ID_LV640U:       /* 29LV640 and 29LV641 have same ID */
323                        info->flash_id += FLASH_AM640U;
324                        info->sector_count = 128;
325                        info->size = 0x00800000 * (sizeof (FPW) / 2);
326                        break;  /* => 8 or 16 MB        */
327
328                case (FPW) INTEL_ID_28F800C3B:
329                        info->flash_id += FLASH_28F800C3B;
330                        info->sector_count = 23;
331                        info->size = 0x00100000 * (sizeof (FPW) / 2);
332                        break;  /* => 1 or 2 MB         */
333
334                case (FPW) INTEL_ID_28F800B3B:
335                        info->flash_id += FLASH_INTEL800B;
336                        info->sector_count = 23;
337                        info->size = 0x00100000 * (sizeof (FPW) / 2);
338                        break;  /* => 1 or 2 MB         */
339
340                case (FPW) INTEL_ID_28F160C3B:
341                        info->flash_id += FLASH_28F160C3B;
342                        info->sector_count = 39;
343                        info->size = 0x00200000 * (sizeof (FPW) / 2);
344                        break;  /* => 2 or 4 MB         */
345
346                case (FPW) INTEL_ID_28F160B3B:
347                        info->flash_id += FLASH_INTEL160B;
348                        info->sector_count = 39;
349                        info->size = 0x00200000 * (sizeof (FPW) / 2);
350                        break;  /* => 2 or 4 MB         */
351
352                case (FPW) INTEL_ID_28F320C3B:
353                        info->flash_id += FLASH_28F320C3B;
354                        info->sector_count = 71;
355                        info->size = 0x00400000 * (sizeof (FPW) / 2);
356                        break;  /* => 4 or 8 MB         */
357
358                case (FPW) INTEL_ID_28F320B3B:
359                        info->flash_id += FLASH_INTEL320B;
360                        info->sector_count = 71;
361                        info->size = 0x00400000 * (sizeof (FPW) / 2);
362                        break;  /* => 4 or 8 MB         */
363
364                case (FPW) INTEL_ID_28F640C3B:
365                        info->flash_id += FLASH_28F640C3B;
366                        info->sector_count = 135;
367                        info->size = 0x00800000 * (sizeof (FPW) / 2);
368                        break;  /* => 8 or 16 MB        */
369
370                case (FPW) INTEL_ID_28F640B3B:
371                        info->flash_id += FLASH_INTEL640B;
372                        info->sector_count = 135;
373                        info->size = 0x00800000 * (sizeof (FPW) / 2);
374                        break;  /* => 8 or 16 MB        */
375
376                default:
377                        info->flash_id = FLASH_UNKNOWN;
378                        info->sector_count = 0;
379                        info->size = 0;
380                        return (0);     /* => no or unknown flash */
381                }
382
383        flash_get_offsets((ulong) addr, info);
384
385        /* Put FLASH back in read mode */
386        flash_reset(info);
387
388        return (info->size);
389}
390#endif /* 0 */
391
392#ifdef CFG_FLASH_PROTECTION
393/*-----------------------------------------------------------------------
394 */
395
396static void
397flash_sync_real_protect(flash_info_t * info)
398{
399        FPWV *addr = (FPWV *) (info->start[0]);
400        FPWV *sect;
401        int i;
402
403        switch (info->flash_id & FLASH_TYPEMASK) {
404        case FLASH_28F800C3B:
405        case FLASH_28F800C3T:
406        case FLASH_28F160C3B:
407        case FLASH_28F160C3T:
408        case FLASH_28F320C3B:
409        case FLASH_28F320C3T:
410        case FLASH_28F640C3B:
411        case FLASH_28F640C3T:
412                /* check for protected sectors */
413                *addr = (FPW) 0x00900090;
414                for (i = 0; i < info->sector_count; i++) {
415                        /* read sector protection at sector address, (A7 .. A0) = 0x02.
416                         * D0 = 1 for each device if protected.
417                         * If at least one device is protected the sector is marked
418                         * protected, but mixed protected and  unprotected devices
419                         * within a sector should never happen.
420                         */
421                        sect = (FPWV *) (info->start[i]);
422                        info->protect[i] =
423                            (sect[2] & (FPW) (0x00010001)) ? 1 : 0;
424                }
425
426                /* Put FLASH back in read mode */
427                flash_reset(info);
428                break;
429
430        case FLASH_AM640U:
431        default:
432                /* no hardware protect that we support */
433                break;
434        }
435}
436#endif
437
438/*-----------------------------------------------------------------------
439 */
440
441int
442flash_erase(flash_info_t * info, int s_first, int s_last)
443{
444        FPWV *addr;
445        int flag, prot, sect;
446        int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
447        ulong start, now, last;
448        int rcode = 0;
449
450        if ((s_first < 0) || (s_first > s_last)) {
451                if (info->flash_id == FLASH_UNKNOWN) {
452                        printf("- missing\n");
453                } else {
454                        printf("- no sectors to erase\n");
455                }
456                return 1;
457        }
458
459        switch (info->flash_id & FLASH_TYPEMASK) {
460        case FLASH_INTEL800B:
461        case FLASH_INTEL160B:
462        case FLASH_INTEL320B:
463        case FLASH_INTEL640B:
464        case FLASH_28F800C3B:
465        case FLASH_28F160C3B:
466        case FLASH_28F320C3B:
467        case FLASH_28F640C3B:
468        case FLASH_AM640U:
469                break;
470        case FLASH_UNKNOWN:
471        default:
472                printf("Can't erase unknown flash type %08lx - aborted\n",
473                       info->flash_id);
474                return 1;
475        }
476
477        prot = 0;
478        for (sect = s_first; sect <= s_last; ++sect) {
479                if (info->protect[sect]) {
480                        prot++;
481                }
482        }
483
484        if (prot) {
485                printf("- Warning: %d protected sectors will not be erased!\n",
486                       prot);
487        } else {
488                printf("\n");
489        }
490
491        start = get_timer(0);
492        last = start;
493
494        /* Start erase on unprotected sectors */
495        for (sect = s_first; sect <= s_last && rcode == 0; sect++) {
496
497                if (info->protect[sect] != 0)   /* protected, skip it */
498                        continue;
499
500                /* Disable interrupts which might cause a timeout here */
501                flag = disable_interrupts();
502
503                addr = (FPWV *) (info->start[sect]);
504                if (intel) {
505                        *addr = (FPW) 0x00500050;       /* clear status register */
506                        *addr = (FPW) 0x00200020;       /* erase setup */
507                        *addr = (FPW) 0x00D000D0;       /* erase confirm */
508                } else {
509                        /* must be AMD style if not Intel */
510                        FPWV *base;     /* first address in bank */
511
512                        base = (FPWV *) (info->start[0]);
513                        base[0x0555] = (FPW) 0x00AA00AA;        /* unlock */
514                        base[0x02AA] = (FPW) 0x00550055;        /* unlock */
515                        base[0x0555] = (FPW) 0x00800080;        /* erase mode */
516                        base[0x0555] = (FPW) 0x00AA00AA;        /* unlock */
517                        base[0x02AA] = (FPW) 0x00550055;        /* unlock */
518                        *addr = (FPW) 0x00300030;       /* erase sector */
519                }
520
521                /* re-enable interrupts if necessary */
522                if (flag)
523                        enable_interrupts();
524
525                /* wait at least 50us for AMD, 80us for Intel.
526                 * Let's wait 1 ms.
527                 */
528                udelay(1000);
529
530                while ((*addr & (FPW) 0x00800080) != (FPW) 0x00800080) {
531                        if ((now = get_timer(0)) - start > CFG_FLASH_ERASE_TOUT) {
532                                printf("Timeout\n");
533
534                                if (intel) {
535                                        /* suspend erase        */
536                                        *addr = (FPW) 0x00B000B0;
537                                }
538
539                                flash_reset(info);      /* reset to read mode */
540                                rcode = 1;      /* failed */
541                                break;
542                        }
543
544                        /* show that we're waiting */
545                        if ((now - last) > 1000) {      /* every second */
546                                putc('.');
547                                last = now;
548                        }
549                }
550
551                flash_reset(info);      /* reset to read mode   */
552        }
553
554        printf(" done\n");
555        return rcode;
556}
557
558/*-----------------------------------------------------------------------
559 * Copy memory to flash, returns:
560 * 0 - OK
561 * 1 - write timeout
562 * 2 - Flash not erased
563 */
564int
565bad_write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
566{
567        FPW data = 0;           /* 16 or 32 bit word, matches flash bus width on MPC8XX */
568        int bytes;              /* number of bytes to program in current word         */
569        int left;               /* number of bytes left to program                    */
570        int i, res;
571
572        for (left = cnt, res = 0;
573             left > 0 && res == 0;
574             addr += sizeof (data), left -= sizeof (data) - bytes) {
575
576                bytes = addr & (sizeof (data) - 1);
577                addr &= ~(sizeof (data) - 1);
578
579                /* combine source and destination data so can program
580                 * an entire word of 16 or 32 bits
581                 */
582                for (i = 0; i < sizeof (data); i++) {
583                        data <<= 8;
584                        if (i < bytes || i - bytes >= left)
585                                data += *((uchar *) addr + i);
586                        else
587                                data += *src++;
588                }
589
590                /* write one word to the flash */
591                switch (info->flash_id & FLASH_VENDMASK) {
592                case FLASH_MAN_AMD:
593                        res = write_word_amd(info, (FPWV *) addr, data);
594                        break;
595                case FLASH_MAN_INTEL:
596                        res = write_word_intel(info, (FPWV *) addr, data);
597                        break;
598                default:
599                        /* unknown flash type, error! */
600                        printf("missing or unknown FLASH type\n");
601                        res = 1;        /* not really a timeout, but gives error */
602                        break;
603                }
604        }
605
606        return (res);
607}
608
609/**
610 * write_buf: - Copy memory to flash.
611 *
612 * @param info:
613 * @param src:  source of copy transaction
614 * @param addr: where to copy to
615 * @param cnt:  number of bytes to copy
616 *
617 * @return      error code
618 */
619
620int
621write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
622{
623        ulong cp, wp;
624        FPW data;
625        int l;
626        int i, rc;
627
628        wp = (addr & ~1);       /* get lower word aligned address */
629
630        /* handle unaligned start bytes */
631        if ((l = addr - wp) != 0) {
632                data = 0;
633                for (i = 0, cp = wp; i < l; ++i, ++cp) {
634                        data = (data >> 8) | (*(uchar *) cp << 8);
635                }
636                for (; i < 2 && cnt > 0; ++i) {
637                        data = (data >> 8) | (*src++ << 8);
638                        --cnt;
639                        ++cp;
640                }
641                for (; cnt == 0 && i < 2; ++i, ++cp) {
642                        data = (data >> 8) | (*(uchar *) cp << 8);
643                }
644
645                if ((rc = write_word(info, (FPWV *)wp, data)) != 0) {
646                        return (rc);
647                }
648                wp += 2;
649        }
650
651        /* handle word aligned part */
652        while (cnt >= 2) {
653                /* data = *((vushort*)src); */
654                data = *((FPW *) src);
655                if ((rc = write_word(info, (FPWV *)wp, data)) != 0) {
656                        return (rc);
657                }
658                src += sizeof (FPW);
659                wp += sizeof (FPW);
660                cnt -= sizeof (FPW);
661        }
662
663        if (cnt == 0)
664                return ERR_OK;
665
666        /*
667         * handle unaligned tail bytes
668         */
669        data = 0;
670        for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
671                data = (data >> 8) | (*src++ << 8);
672                --cnt;
673        }
674        for (; i < 2; ++i, ++cp) {
675                data = (data >> 8) | (*(uchar *) cp << 8);
676        }
677
678        return write_word(info, (FPWV *)wp, data);
679}
680
681/*-----------------------------------------------------------------------
682 * Write a word to Flash for AMD FLASH
683 * A word is 16 or 32 bits, whichever the bus width of the flash bank
684 * (not an individual chip) is.
685 *
686 * returns:
687 * 0 - OK
688 * 1 - write timeout
689 * 2 - Flash not erased
690 */
691static int
692write_word_amd(flash_info_t * info, FPWV * dest, FPW data)
693{
694        ulong start;
695        int flag;
696        int res = 0;            /* result, assume success       */
697        FPWV *base;             /* first address in flash bank  */
698
699        /* Check if Flash is (sufficiently) erased */
700        if ((*dest & data) != data) {
701                return (2);
702        }
703
704        base = (FPWV *) (info->start[0]);
705        /* Disable interrupts which might cause a timeout here */
706        flag = disable_interrupts();
707
708        base[0x0555] = (FPW) 0x00AA00AA;        /* unlock */
709        base[0x02AA] = (FPW) 0x00550055;        /* unlock */
710        base[0x0555] = (FPW) 0x00A000A0;        /* selects program mode */
711
712        *dest = data;           /* start programming the data   */
713
714        /* re-enable interrupts if necessary */
715        if (flag)
716                enable_interrupts();
717
718        start = get_timer(0);
719
720        /* data polling for D7 */
721        while (res == 0
722               && (*dest & (FPW) 0x00800080) != (data & (FPW) 0x00800080)) {
723                if (get_timer(0) - start > CFG_FLASH_WRITE_TOUT) {
724                        *dest = (FPW) 0x00F000F0;       /* reset bank */
725                        printf("SHA timeout\n");
726                        res = 1;
727                }
728        }
729
730        return (res);
731}
732
733/*-----------------------------------------------------------------------
734 * Write a word to Flash for Intel FLASH
735 * A word is 16 or 32 bits, whichever the bus width of the flash bank
736 * (not an individual chip) is.
737 *
738 * returns:
739 * 0 - OK
740 * 1 - write timeout
741 * 2 - Flash not erased
742 */
743static int
744write_word_intel(flash_info_t * info, FPWV * dest, FPW data)
745{
746        ulong start;
747        int flag;
748        int res = 0;            /* result, assume success       */
749
750        /* Check if Flash is (sufficiently) erased */
751        if ((*dest & data) != data) {
752                return (2);
753        }
754
755        /* Disable interrupts which might cause a timeout here */
756        flag = disable_interrupts();
757
758        *dest = (FPW) 0x00500050;       /* clear status register        */
759        *dest = (FPW) 0x00FF00FF;       /* make sure in read mode       */
760        *dest = (FPW) 0x00400040;       /* program setup                */
761
762        *dest = data;           /* start programming the data   */
763
764        /* re-enable interrupts if necessary */
765        if (flag)
766                enable_interrupts();
767
768        start = get_timer(0);
769
770        while (res == 0 && (*dest & (FPW) 0x00800080) != (FPW) 0x00800080) {
771                if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
772                        *dest = (FPW) 0x00B000B0;       /* Suspend program      */
773                        res = 1;
774                }
775        }
776
777        if (res == 0 && (*dest & (FPW) 0x00100010))
778                res = 1;        /* write failed, time out error is close enough */
779
780        *dest = (FPW) 0x00500050;       /* clear status register        */
781        *dest = (FPW) 0x00FF00FF;       /* make sure in read mode       */
782
783        return (res);
784}
785
786#ifdef CFG_FLASH_PROTECTION
787/*-----------------------------------------------------------------------
788 */
789int
790flash_real_protect(flash_info_t * info, long sector, int prot)
791{
792        int rcode = 0;          /* assume success */
793        FPWV *addr;             /* address of sector */
794        FPW value;
795
796        addr = (FPWV *) (info->start[sector]);
797
798        switch (info->flash_id & FLASH_TYPEMASK) {
799        case FLASH_28F800C3B:
800        case FLASH_28F800C3T:
801        case FLASH_28F160C3B:
802        case FLASH_28F160C3T:
803        case FLASH_28F320C3B:
804        case FLASH_28F320C3T:
805        case FLASH_28F640C3B:
806        case FLASH_28F640C3T:
807                flash_reset(info);      /* make sure in read mode */
808                *addr = (FPW) 0x00600060L;      /* lock command setup */
809                if (prot)
810                        *addr = (FPW) 0x00010001L;      /* lock sector */
811                else
812                        *addr = (FPW) 0x00D000D0L;      /* unlock sector */
813                flash_reset(info);      /* reset to read mode */
814
815                /* now see if it really is locked/unlocked as requested */
816                *addr = (FPW) 0x00900090;
817                /* read sector protection at sector address, (A7 .. A0) = 0x02.
818                 * D0 = 1 for each device if protected.
819                 * If at least one device is protected the sector is marked
820                 * protected, but return failure. Mixed protected and
821                 * unprotected devices within a sector should never happen.
822                 */
823                value = addr[2] & (FPW) 0x00010001;
824                if (value == 0)
825                        info->protect[sector] = 0;
826                else if (value == (FPW) 0x00010001)
827                        info->protect[sector] = 1;
828                else {
829                        /* error, mixed protected and unprotected */
830                        rcode = 1;
831                        info->protect[sector] = 1;
832                }
833                if (info->protect[sector] != prot)
834                        rcode = 1;      /* failed to protect/unprotect as requested */
835
836                /* reload all protection bits from hardware for now */
837                flash_sync_real_protect(info);
838                break;
839
840        case FLASH_AM640U:
841        default:
842                /* no hardware protect that we support */
843                info->protect[sector] = prot;
844                break;
845        }
846
847        return rcode;
848}
849#endif
Note: See TracBrowser for help on using the repository browser.