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