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