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