uboot/board/mpl/common/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000, 2001
   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/*
  25 * Modified 4/5/2001
  26 * Wait for completion of each sector erase command issued
  27 * 4/5/2001
  28 * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
  29 */
  30
  31/*
  32 * Modified 3/7/2001
  33 * - adapted for pip405, Denis Peter, MPL AG Switzerland
  34 * TODO:
  35 * clean-up
  36 */
  37
  38#include <common.h>
  39
  40#if !defined(CONFIG_PATI)
  41#include <ppc4xx.h>
  42#include <asm/processor.h>
  43#include "common_util.h"
  44#if defined(CONFIG_MIP405)
  45#include "../mip405/mip405.h"
  46#endif
  47#if defined(CONFIG_PIP405)
  48#include "../pip405/pip405.h"
  49#endif
  50#include <asm/4xx_pci.h>
  51#else /* defined(CONFIG_PATI) */
  52#include <mpc5xx.h>
  53#endif
  54
  55flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  56/*-----------------------------------------------------------------------
  57 * Functions
  58 */
  59static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  60static int write_word (flash_info_t *info, ulong dest, ulong data);
  61
  62void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt);
  63
  64#define ADDR0           0x5555
  65#define ADDR1           0x2aaa
  66#define FLASH_WORD_SIZE unsigned short
  67
  68#define FALSE           0
  69#define TRUE            1
  70
  71#if !defined(CONFIG_PATI)
  72
  73/*-----------------------------------------------------------------------
  74 * Some CS switching routines:
  75 *
  76 * On PIP/MIP405 we have 3 (4) possible boot mode
  77 *
  78 * - Boot from Flash (Flash CS = CS0, MPS CS = CS1)
  79 * - Boot from MPS   (Flash CS = CS1, MPS CS = CS0)
  80 * - Boot from PCI with Flash map (Flash CS = CS0, MPS CS = CS1)
  81 * - Boot from PCI with MPS map   (Flash CS = CS1, MPS CS = CS0)
  82 * The flash init is the first board specific routine which is called
  83 * after code relocation (running from SDRAM)
  84 * The first thing we do is to map the Flash CS to the Flash area and
  85 * the MPS CS to the MPS area. Since the flash size is unknown at this
  86 * point, we use the max flash size and the lowest flash address as base.
  87 *
  88 * After flash detection we adjust the size of the CS area accordingly.
  89 * The board_init_r will fill in wrong values in the board init structure,
  90 * but this will be fixed in the misc_init_r routine:
  91 * bd->bi_flashstart=0-flash_info[0].size
  92 * bd->bi_flashsize=flash_info[0].size-CONFIG_SYS_MONITOR_LEN
  93 * bd->bi_flashoffset=0
  94 *
  95 */
  96int get_boot_mode(void)
  97{
  98        unsigned long pbcr;
  99        int res = 0;
 100        pbcr = mfdcr (CPC0_PSR);
 101        if ((pbcr & PSR_ROM_WIDTH_MASK) == 0)
 102                /* boot via MPS or MPS mapping */
 103                res = BOOT_MPS;
 104        if(pbcr & PSR_ROM_LOC)
 105                /* boot via PCI.. */
 106                res |= BOOT_PCI;
 107         return res;
 108}
 109
 110/* Map the flash high (in boot area)
 111   This code can only be executed from SDRAM (after relocation).
 112*/
 113void setup_cs_reloc(void)
 114{
 115        int mode;
 116        /* Since we are relocated, we can set-up the CS finaly
 117         * but first of all, switch off PCI mapping (in case it was a PCI boot) */
 118        out32r(PMM0MA,0L);
 119        icache_enable (); /* we are relocated */
 120        /* get boot mode */
 121        mode=get_boot_mode();
 122        /* we map the flash high in every case */
 123        /* first findout on which cs the flash is */
 124        if(mode & BOOT_MPS) {
 125                /* map flash high on CS1 and MPS on CS0 */
 126                mtdcr (EBC0_CFGADDR, PB0AP);
 127                mtdcr (EBC0_CFGDATA, MPS_AP);
 128                mtdcr (EBC0_CFGADDR, PB0CR);
 129                mtdcr (EBC0_CFGDATA, MPS_CR);
 130                /* we use the default values (max values) for the flash
 131                 * because its real size is not yet known */
 132                mtdcr (EBC0_CFGADDR, PB1AP);
 133                mtdcr (EBC0_CFGDATA, FLASH_AP);
 134                mtdcr (EBC0_CFGADDR, PB1CR);
 135                mtdcr (EBC0_CFGDATA, FLASH_CR_B);
 136        }
 137        else {
 138                /* map flash high on CS0 and MPS on CS1 */
 139                mtdcr (EBC0_CFGADDR, PB1AP);
 140                mtdcr (EBC0_CFGDATA, MPS_AP);
 141                mtdcr (EBC0_CFGADDR, PB1CR);
 142                mtdcr (EBC0_CFGDATA, MPS_CR);
 143                /* we use the default values (max values) for the flash
 144                 * because its real size is not yet known */
 145                mtdcr (EBC0_CFGADDR, PB0AP);
 146                mtdcr (EBC0_CFGDATA, FLASH_AP);
 147                mtdcr (EBC0_CFGADDR, PB0CR);
 148                mtdcr (EBC0_CFGDATA, FLASH_CR_B);
 149        }
 150}
 151
 152#endif /* #if !defined(CONFIG_PATI) */
 153
 154unsigned long flash_init (void)
 155{
 156        unsigned long size_b0;
 157        int i;
 158
 159#if !defined(CONFIG_PATI)
 160        unsigned long size_b1,flashcr,size_reg;
 161        int mode;
 162        extern char version_string;
 163        char *p = &version_string;
 164
 165        /* Since we are relocated, we can set-up the CS finally */
 166        setup_cs_reloc();
 167        /* get and display boot mode */
 168        mode=get_boot_mode();
 169        if(mode & BOOT_PCI)
 170                printf("(PCI Boot %s Map) ",(mode & BOOT_MPS) ?
 171                        "MPS" : "Flash");
 172        else
 173                printf("(%s Boot) ",(mode & BOOT_MPS) ?
 174                        "MPS" : "Flash");
 175#endif /* #if !defined(CONFIG_PATI) */
 176        /* Init: no FLASHes known */
 177        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
 178                flash_info[i].flash_id = FLASH_UNKNOWN;
 179        }
 180
 181        /* Static FLASH Bank configuration here - FIXME XXX */
 182
 183        size_b0 = flash_get_size((vu_long *)CONFIG_SYS_MONITOR_BASE, &flash_info[0]);
 184
 185        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
 186                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
 187                        size_b0, size_b0<<20);
 188        }
 189        /* protect the bootloader */
 190        /* Monitor protection ON by default */
 191#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
 192        flash_protect(FLAG_PROTECT_SET,
 193                        CONFIG_SYS_MONITOR_BASE,
 194                        CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
 195                        &flash_info[0]);
 196#endif
 197#if !defined(CONFIG_PATI)
 198        /* protect reset vector */
 199        flash_info[0].protect[flash_info[0].sector_count-1] = 1;
 200        size_b1 = 0 ;
 201        flash_info[0].size = size_b0;
 202        /* set up flash cs according to the size */
 203        size_reg=(flash_info[0].size >>20);
 204        switch (size_reg) {
 205                case 0:
 206                case 1: i=0; break; /* <= 1MB */
 207                case 2: i=1; break; /* = 2MB */
 208                case 4: i=2; break; /* = 4MB */
 209                case 8: i=3; break; /* = 8MB */
 210                case 16: i=4; break; /* = 16MB */
 211                case 32: i=5; break; /* = 32MB */
 212                case 64: i=6; break; /* = 64MB */
 213                case 128: i=7; break; /*= 128MB */
 214                default:
 215                        printf("\n #### ERROR, wrong size %ld MByte reset board #####\n",size_reg);
 216                        while(1);
 217        }
 218        if(mode & BOOT_MPS) {
 219                /* flash is on CS1 */
 220                mtdcr(EBC0_CFGADDR, PB1CR);
 221                flashcr = mfdcr (EBC0_CFGDATA);
 222                /* we map the flash high in every case */
 223                flashcr&=0x0001FFFF; /* mask out address bits */
 224                flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */
 225                flashcr|= (i << 17); /* size addr */
 226                mtdcr(EBC0_CFGADDR, PB1CR);
 227                mtdcr(EBC0_CFGDATA, flashcr);
 228        }
 229        else {
 230                /* flash is on CS0 */
 231                mtdcr(EBC0_CFGADDR, PB0CR);
 232                flashcr = mfdcr (EBC0_CFGDATA);
 233                /* we map the flash high in every case */
 234                flashcr&=0x0001FFFF; /* mask out address bits */
 235                flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */
 236                flashcr|= (i << 17); /* size addr */
 237                mtdcr(EBC0_CFGADDR, PB0CR);
 238                mtdcr(EBC0_CFGDATA, flashcr);
 239        }
 240#if 0
 241        /* enable this (PIP405/MIP405 only) if you want to test if
 242           the relocation has be done ok.
 243           This will disable both Chipselects */
 244        mtdcr (EBC0_CFGADDR, PB0CR);
 245        mtdcr (EBC0_CFGDATA, 0L);
 246        mtdcr (EBC0_CFGADDR, PB1CR);
 247        mtdcr (EBC0_CFGDATA, 0L);
 248        printf("CS0 & CS1 switched off for test\n");
 249#endif
 250        /* patch version_string */
 251        for(i=0;i<0x100;i++) {
 252                if(*p=='\n') {
 253                        *p=0;
 254                        break;
 255                }
 256                p++;
 257        }
 258#else /* #if !defined(CONFIG_PATI) */
 259#ifdef  CONFIG_ENV_IS_IN_FLASH
 260        /* ENV protection ON by default */
 261        flash_protect(FLAG_PROTECT_SET,
 262                      CONFIG_ENV_ADDR,
 263                      CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
 264                      &flash_info[0]);
 265#endif
 266#endif /* #if !defined(CONFIG_PATI) */
 267        return (size_b0);
 268}
 269
 270
 271/*-----------------------------------------------------------------------
 272 */
 273void flash_print_info  (flash_info_t *info)
 274{
 275        int i;
 276        int k;
 277        int size;
 278        int erased;
 279        volatile unsigned long *flash;
 280
 281        if (info->flash_id == FLASH_UNKNOWN) {
 282                printf ("missing or unknown FLASH type\n");
 283                return;
 284        }
 285
 286        switch (info->flash_id & FLASH_VENDMASK) {
 287        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 288        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
 289        case FLASH_MAN_SST:     printf ("SST ");                break;
 290        case FLASH_MAN_INTEL:   printf ("Intel ");              break;
 291        default:                printf ("Unknown Vendor ");     break;
 292        }
 293
 294        switch (info->flash_id & FLASH_TYPEMASK) {
 295        case FLASH_AM040:       printf ("AM29F040 (512 Kbit, uniform sector size)\n");
 296                                break;
 297        case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
 298                                break;
 299        case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
 300                                break;
 301        case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
 302                                break;
 303        case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
 304                                break;
 305        case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
 306                                break;
 307        case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
 308                                break;
 309        case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
 310                                break;
 311        case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
 312                                break;
 313        case FLASH_SST800A:     printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
 314                                break;
 315        case FLASH_SST160A:     printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
 316                                break;
 317        case FLASH_INTEL320T:   printf ("TE28F320C3 (32 Mbit, top sector size)\n");
 318                                break;
 319        case FLASH_AM640U:      printf ("AM29LV640U (64 Mbit, uniform sector size)\n");
 320                                break;
 321        default:                printf ("Unknown Chip Type\n");
 322                                break;
 323        }
 324
 325        printf ("  Size: %ld KB in %d Sectors\n",
 326                info->size >> 10, info->sector_count);
 327
 328        printf ("  Sector Start Addresses:");
 329        for (i=0; i<info->sector_count; ++i) {
 330                /*
 331                 * Check if whole sector is erased
 332                */
 333                if (i != (info->sector_count-1))
 334                        size = info->start[i+1] - info->start[i];
 335                else
 336                        size = info->start[0] + info->size - info->start[i];
 337                erased = 1;
 338                flash = (volatile unsigned long *)info->start[i];
 339                size = size >> 2;        /* divide by 4 for longword access */
 340                for (k=0; k<size; k++) {
 341                        if (*flash++ != 0xffffffff) {
 342                                erased = 0;
 343                                break;
 344                        }
 345                }
 346                if ((i % 5) == 0)
 347                        printf ("\n   ");
 348                printf (" %08lX%s%s",
 349                        info->start[i],
 350                        erased ? " E" : "  ",
 351                        info->protect[i] ? "RO " : "   ");
 352        }
 353        printf ("\n");
 354}
 355
 356/*-----------------------------------------------------------------------
 357 */
 358
 359
 360/*-----------------------------------------------------------------------
 361
 362*/
 363
 364/*
 365 * The following code cannot be run from FLASH!
 366 */
 367static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 368{
 369        short i;
 370        FLASH_WORD_SIZE value;
 371        ulong base;
 372        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
 373
 374        /* Write auto select command: read Manufacturer ID */
 375        addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 376        addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 377        addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090;
 378
 379        value = addr2[0];
 380        /*      printf("flash_get_size value: %x\n",value); */
 381        switch (value) {
 382        case (FLASH_WORD_SIZE)AMD_MANUFACT:
 383                info->flash_id = FLASH_MAN_AMD;
 384                break;
 385        case (FLASH_WORD_SIZE)FUJ_MANUFACT:
 386                info->flash_id = FLASH_MAN_FUJ;
 387                break;
 388        case (FLASH_WORD_SIZE)INTEL_MANUFACT:
 389                info->flash_id = FLASH_MAN_INTEL;
 390                break;
 391        case (FLASH_WORD_SIZE)SST_MANUFACT:
 392                info->flash_id = FLASH_MAN_SST;
 393                break;
 394        default:
 395                info->flash_id = FLASH_UNKNOWN;
 396                info->sector_count = 0;
 397                info->size = 0;
 398                return (0);                     /* no or unknown flash  */
 399        }
 400        value = addr2[1];                       /* device ID            */
 401        /*      printf("Device value %x\n",value);                  */
 402        switch (value) {
 403        case (FLASH_WORD_SIZE)AMD_ID_F040B:
 404                info->flash_id += FLASH_AM040;
 405                info->sector_count = 8;
 406                info->size = 0x0080000; /* => 512 ko */
 407                break;
 408        case (FLASH_WORD_SIZE)AMD_ID_LV400T:
 409                info->flash_id += FLASH_AM400T;
 410                info->sector_count = 11;
 411                info->size = 0x00080000;
 412                break;                          /* => 0.5 MB            */
 413
 414        case (FLASH_WORD_SIZE)AMD_ID_LV400B:
 415                info->flash_id += FLASH_AM400B;
 416                info->sector_count = 11;
 417                info->size = 0x00080000;
 418                break;                          /* => 0.5 MB            */
 419
 420        case (FLASH_WORD_SIZE)AMD_ID_LV800T:
 421                info->flash_id += FLASH_AM800T;
 422                info->sector_count = 19;
 423                info->size = 0x00100000;
 424                break;                          /* => 1 MB              */
 425
 426        case (FLASH_WORD_SIZE)AMD_ID_LV800B:
 427                info->flash_id += FLASH_AM800B;
 428                info->sector_count = 19;
 429                info->size = 0x00100000;
 430                break;                          /* => 1 MB              */
 431
 432        case (FLASH_WORD_SIZE)AMD_ID_LV160T:
 433                info->flash_id += FLASH_AM160T;
 434                info->sector_count = 35;
 435                info->size = 0x00200000;
 436                break;                          /* => 2 MB              */
 437
 438        case (FLASH_WORD_SIZE)AMD_ID_LV160B:
 439                info->flash_id += FLASH_AM160B;
 440                info->sector_count = 35;
 441                info->size = 0x00200000;
 442                break;                          /* => 2 MB              */
 443        case (FLASH_WORD_SIZE)AMD_ID_LV320T:
 444                info->flash_id += FLASH_AM320T;
 445                info->sector_count = 67;
 446                info->size = 0x00400000;
 447                break;                          /* => 4 MB              */
 448        case (FLASH_WORD_SIZE)AMD_ID_LV640U:
 449                info->flash_id += FLASH_AM640U;
 450                info->sector_count = 128;
 451                info->size = 0x00800000;
 452                break;                          /* => 8 MB              */
 453#if 0   /* enable when device IDs are available */
 454
 455        case (FLASH_WORD_SIZE)AMD_ID_LV320B:
 456                info->flash_id += FLASH_AM320B;
 457                info->sector_count = 67;
 458                info->size = 0x00400000;
 459                break;                          /* => 4 MB              */
 460#endif
 461        case (FLASH_WORD_SIZE)SST_ID_xF800A:
 462                info->flash_id += FLASH_SST800A;
 463                info->sector_count = 16;
 464                info->size = 0x00100000;
 465                break;                          /* => 1 MB              */
 466        case (FLASH_WORD_SIZE)INTEL_ID_28F320C3T:
 467                info->flash_id += FLASH_INTEL320T;
 468                info->sector_count = 71;
 469                info->size = 0x00400000;
 470                break;                          /* => 4 MB              */
 471
 472
 473        case (FLASH_WORD_SIZE)SST_ID_xF160A:
 474                info->flash_id += FLASH_SST160A;
 475                info->sector_count = 32;
 476                info->size = 0x00200000;
 477                break;                          /* => 2 MB              */
 478
 479        default:
 480                info->flash_id = FLASH_UNKNOWN;
 481                return (0);                     /* => no or unknown flash */
 482
 483        }
 484        /* base address calculation */
 485        base=0-info->size;
 486        /* set up sector start address table */
 487        if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
 488             (info->flash_id  == FLASH_AM040) ||
 489             (info->flash_id  == FLASH_AM640U)){
 490                for (i = 0; i < info->sector_count; i++)
 491                        info->start[i] = base + (i * 0x00010000);
 492        }
 493        else {
 494                if (info->flash_id & FLASH_BTYPE) {
 495                        /* set sector offsets for bottom boot block type        */
 496                        info->start[0] = base + 0x00000000;
 497                        info->start[1] = base + 0x00004000;
 498                        info->start[2] = base + 0x00006000;
 499                        info->start[3] = base + 0x00008000;
 500                        for (i = 4; i < info->sector_count; i++)
 501                                info->start[i] = base + (i * 0x00010000) - 0x00030000;
 502                }
 503                else {
 504                        /* set sector offsets for top boot block type           */
 505                        i = info->sector_count - 1;
 506                        if(info->sector_count==71) {
 507
 508                                info->start[i--] = base + info->size - 0x00002000;
 509                                info->start[i--] = base + info->size - 0x00004000;
 510                                info->start[i--] = base + info->size - 0x00006000;
 511                                info->start[i--] = base + info->size - 0x00008000;
 512                                info->start[i--] = base + info->size - 0x0000A000;
 513                                info->start[i--] = base + info->size - 0x0000C000;
 514                                info->start[i--] = base + info->size - 0x0000E000;
 515                                for (; i >= 0; i--)
 516                                        info->start[i] = base + i * 0x000010000;
 517                        }
 518                        else {
 519                                info->start[i--] = base + info->size - 0x00004000;
 520                                info->start[i--] = base + info->size - 0x00006000;
 521                                info->start[i--] = base + info->size - 0x00008000;
 522                                for (; i >= 0; i--)
 523                                        info->start[i] = base + i * 0x00010000;
 524                        }
 525                }
 526        }
 527
 528        /* check for protected sectors */
 529        for (i = 0; i < info->sector_count; i++) {
 530                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 531                /* D0 = 1 if protected */
 532                addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
 533                if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
 534                        info->protect[i] = 0;
 535                else
 536                        info->protect[i] = addr2[2] & 1;
 537        }
 538
 539        /*
 540         * Prevent writes to uninitialized FLASH.
 541         */
 542        if (info->flash_id != FLASH_UNKNOWN) {
 543                addr2 = (FLASH_WORD_SIZE *)info->start[0];
 544                *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
 545        }
 546        return (info->size);
 547}
 548
 549
 550int wait_for_DQ7(flash_info_t *info, int sect)
 551{
 552        ulong start, now, last;
 553        volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
 554
 555        start = get_timer (0);
 556        last  = start;
 557        while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
 558                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 559                        printf ("Timeout\n");
 560                        return ERR_TIMOUT;
 561                }
 562                /* show that we're waiting */
 563                if ((now - last) > 1000) {  /* every second */
 564                        putc ('.');
 565                        last = now;
 566                }
 567        }
 568        return ERR_OK;
 569}
 570
 571int intel_wait_for_DQ7(flash_info_t *info, int sect)
 572{
 573        ulong start, now, last, status;
 574        volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
 575
 576        start = get_timer (0);
 577        last  = start;
 578        while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
 579                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 580                        printf ("Timeout\n");
 581                        return ERR_TIMOUT;
 582                }
 583                /* show that we're waiting */
 584                if ((now - last) > 1000) {  /* every second */
 585                        putc ('.');
 586                        last = now;
 587                }
 588        }
 589        status = addr[0] & (FLASH_WORD_SIZE)0x00280028;
 590        /* clear status register */
 591        addr[0] = (FLASH_WORD_SIZE)0x00500050;
 592        /* check status for block erase fail and VPP low */
 593        return (status == 0 ? ERR_OK : ERR_NOT_ERASED);
 594}
 595
 596/*-----------------------------------------------------------------------
 597 */
 598
 599int     flash_erase (flash_info_t *info, int s_first, int s_last)
 600{
 601        volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
 602        volatile FLASH_WORD_SIZE *addr2;
 603        int flag, prot, sect, l_sect;
 604        int i, rcode = 0;
 605
 606
 607        if ((s_first < 0) || (s_first > s_last)) {
 608                if (info->flash_id == FLASH_UNKNOWN) {
 609                        printf ("- missing\n");
 610                } else {
 611                        printf ("- no sectors to erase\n");
 612                }
 613                return 1;
 614        }
 615
 616        if (info->flash_id == FLASH_UNKNOWN) {
 617                printf ("Can't erase unknown flash type - aborted\n");
 618                return 1;
 619        }
 620
 621        prot = 0;
 622        for (sect=s_first; sect<=s_last; ++sect) {
 623                if (info->protect[sect]) {
 624                        prot++;
 625                }
 626        }
 627
 628        if (prot) {
 629                printf ("- Warning: %d protected sectors will not be erased!\n",
 630                        prot);
 631        } else {
 632                printf ("\n");
 633        }
 634
 635        l_sect = -1;
 636
 637        /* Disable interrupts which might cause a timeout here */
 638        flag = disable_interrupts();
 639
 640        /* Start erase on unprotected sectors */
 641        for (sect = s_first; sect<=s_last; sect++) {
 642                if (info->protect[sect] == 0) { /* not protected */
 643                        addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);
 644                        /*  printf("Erasing sector %p\n", addr2); */ /* CLH */
 645                        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
 646                                addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 647                                addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 648                                addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
 649                                addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 650                                addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 651                                addr2[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
 652                                for (i=0; i<50; i++)
 653                                        udelay(1000);  /* wait 1 ms */
 654                                rcode |= wait_for_DQ7(info, sect);
 655                        }
 656                        else {
 657                                if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
 658                                        addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector */
 659                                        addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
 660                                        intel_wait_for_DQ7(info, sect);
 661                                        addr2[0] = (FLASH_WORD_SIZE)0x00200020;  /* sector erase */
 662                                        addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
 663                                        rcode |= intel_wait_for_DQ7(info, sect);
 664                                }
 665                                else {
 666                                        addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 667                                        addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 668                                        addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
 669                                        addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 670                                        addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 671                                        addr2[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
 672                                        rcode |= wait_for_DQ7(info, sect);
 673                                }
 674                        }
 675                        l_sect = sect;
 676                        /*
 677                         * Wait for each sector to complete, it's more
 678                         * reliable.  According to AMD Spec, you must
 679                         * issue all erase commands within a specified
 680                         * timeout.  This has been seen to fail, especially
 681                         * if printf()s are included (for debug)!!
 682                         */
 683                        /*   wait_for_DQ7(info, sect); */
 684                }
 685        }
 686
 687        /* re-enable interrupts if necessary */
 688        if (flag)
 689                enable_interrupts();
 690
 691        /* wait at least 80us - let's wait 1 ms */
 692        udelay (1000);
 693
 694#if 0
 695        /*
 696         * We wait for the last triggered sector
 697         */
 698        if (l_sect < 0)
 699                goto DONE;
 700        wait_for_DQ7(info, l_sect);
 701
 702DONE:
 703#endif
 704        /* reset to read mode */
 705        addr = (FLASH_WORD_SIZE *)info->start[0];
 706        addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
 707
 708        if (!rcode)
 709            printf (" done\n");
 710
 711        return rcode;
 712}
 713
 714
 715void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt)
 716{
 717        int i;
 718        volatile FLASH_WORD_SIZE *addr2;
 719        long c;
 720        c= (long)cnt;
 721        for(i=info->sector_count-1;i>0;i--)
 722        {
 723                if(addr>=info->start[i])
 724                        break;
 725        }
 726        do {
 727                addr2 = (FLASH_WORD_SIZE *)(info->start[i]);
 728                addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector setup */
 729                addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* unlock sector */
 730                intel_wait_for_DQ7(info, i);
 731                i++;
 732                c-=(info->start[i]-info->start[i-1]);
 733        }while(c>0);
 734}
 735
 736
 737/*-----------------------------------------------------------------------
 738 * Copy memory to flash, returns:
 739 * 0 - OK
 740 * 1 - write timeout
 741 * 2 - Flash not erased
 742 */
 743
 744int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 745{
 746        ulong cp, wp, data;
 747        int i, l, rc;
 748
 749        if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
 750                unlock_intel_sectors(info,addr,cnt);
 751        }
 752        wp = (addr & ~3);       /* get lower word aligned address */
 753        /*
 754         * handle unaligned start bytes
 755         */
 756        if ((l = addr - wp) != 0) {
 757                data = 0;
 758                for (i=0, cp=wp; i<l; ++i, ++cp) {
 759                        data = (data << 8) | (*(uchar *)cp);
 760                }
 761                for (; i<4 && cnt>0; ++i) {
 762                        data = (data << 8) | *src++;
 763                        --cnt;
 764                        ++cp;
 765                }
 766                for (; cnt==0 && i<4; ++i, ++cp) {
 767                        data = (data << 8) | (*(uchar *)cp);
 768                }
 769
 770                if ((rc = write_word(info, wp, data)) != 0) {
 771                        return (rc);
 772                }
 773                wp += 4;
 774        }
 775
 776        /*
 777         * handle word aligned part
 778         */
 779        while (cnt >= 4) {
 780                data = 0;
 781                for (i=0; i<4; ++i) {
 782                        data = (data << 8) | *src++;
 783                }
 784                if ((rc = write_word(info, wp, data)) != 0) {
 785                        return (rc);
 786                }
 787                wp  += 4;
 788                if((wp % 0x10000)==0)
 789                        printf("."); /* show Progress */
 790                cnt -= 4;
 791        }
 792
 793        if (cnt == 0) {
 794                return (0);
 795        }
 796
 797        /*
 798         * handle unaligned tail bytes
 799         */
 800        data = 0;
 801        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 802                data = (data << 8) | *src++;
 803                --cnt;
 804        }
 805        for (; i<4; ++i, ++cp) {
 806                data = (data << 8) | (*(uchar *)cp);
 807        }
 808        rc=write_word(info, wp, data);
 809        return rc;
 810}
 811
 812/*-----------------------------------------------------------------------
 813 * Write a word to Flash, returns:
 814 * 0 - OK
 815 * 1 - write timeout
 816 * 2 - Flash not erased
 817 */
 818static FLASH_WORD_SIZE *read_val = (FLASH_WORD_SIZE *)0x200000;
 819
 820static int write_word (flash_info_t *info, ulong dest, ulong data)
 821{
 822        volatile FLASH_WORD_SIZE *addr2 = (volatile FLASH_WORD_SIZE *)(info->start[0]);
 823        volatile FLASH_WORD_SIZE *dest2 = (volatile FLASH_WORD_SIZE *)dest;
 824        volatile FLASH_WORD_SIZE *data2;
 825        ulong start;
 826        ulong *data_p;
 827        int flag;
 828        int i;
 829
 830        data_p = &data;
 831        data2 = (volatile FLASH_WORD_SIZE *)data_p;
 832
 833        /* Check if Flash is (sufficiently) erased */
 834        if ((*((volatile FLASH_WORD_SIZE *)dest) &
 835                (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
 836                return (2);
 837        }
 838        /* Disable interrupts which might cause a timeout here */
 839        flag = disable_interrupts();
 840        for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
 841        {
 842                if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
 843                        /* intel style writting */
 844                        dest2[i] = (FLASH_WORD_SIZE)0x00500050;
 845                        dest2[i] = (FLASH_WORD_SIZE)0x00400040;
 846                        *read_val++ = data2[i];
 847                        dest2[i] = data2[i];
 848                        if (flag)
 849                                enable_interrupts();
 850                        /* data polling for D7 */
 851                        start = get_timer (0);
 852                        udelay(10);
 853                        while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080)
 854                        {
 855                                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
 856                                        return (1);
 857                        }
 858                        dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
 859                        udelay(10);
 860                        dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
 861                        if(dest2[i]!=data2[i])
 862                                printf("Error at %p 0x%04X != 0x%04X\n",&dest2[i],dest2[i],data2[i]);
 863                }
 864                else {
 865                        addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 866                        addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 867                        addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0;
 868                        dest2[i] = data2[i];
 869                        /* re-enable interrupts if necessary */
 870                        if (flag)
 871                                enable_interrupts();
 872                        /* data polling for D7 */
 873                        start = get_timer (0);
 874                        while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) !=
 875                                (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
 876                                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 877                                        return (1);
 878                                }
 879                        }
 880                }
 881        }
 882        return (0);
 883}
 884
 885/*-----------------------------------------------------------------------
 886 */
 887