uboot/board/sandpoint/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <mpc824x.h>
  26#include <asm/processor.h>
  27#include <asm/pci_io.h>
  28#include <w83c553f.h>
  29
  30#define ROM_CS0_START   0xFF800000
  31#define ROM_CS1_START   0xFF000000
  32
  33flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips    */
  34
  35#if defined(CONFIG_ENV_IS_IN_FLASH)
  36# ifndef  CONFIG_ENV_ADDR
  37#  define CONFIG_ENV_ADDR  (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
  38# endif
  39# ifndef  CONFIG_ENV_SIZE
  40#  define CONFIG_ENV_SIZE  CONFIG_ENV_SECT_SIZE
  41# endif
  42# ifndef  CONFIG_ENV_SECT_SIZE
  43#  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
  44# endif
  45#endif
  46
  47/*-----------------------------------------------------------------------
  48 * Functions
  49 */
  50static int write_word (flash_info_t *info, ulong dest, ulong data);
  51#if 0
  52static void flash_get_offsets (ulong base, flash_info_t *info);
  53#endif /* 0 */
  54
  55/*flash command address offsets*/
  56
  57#if 0
  58#define ADDR0           (0x555)
  59#define ADDR1           (0x2AA)
  60#define ADDR3           (0x001)
  61#else
  62#define ADDR0           (0xAAA)
  63#define ADDR1           (0x555)
  64#define ADDR3           (0x001)
  65#endif
  66
  67#define FLASH_WORD_SIZE unsigned char
  68
  69/*-----------------------------------------------------------------------
  70 */
  71
  72#if 0
  73static int byte_parity_odd(unsigned char x) __attribute__ ((const));
  74#endif /* 0 */
  75static unsigned long flash_id(unsigned char mfct, unsigned char chip) __attribute__ ((const));
  76
  77typedef struct
  78{
  79  FLASH_WORD_SIZE extval;
  80  unsigned short intval;
  81} map_entry;
  82
  83#if 0
  84static int
  85byte_parity_odd(unsigned char x)
  86{
  87  x ^= x >> 4;
  88  x ^= x >> 2;
  89  x ^= x >> 1;
  90  return (x & 0x1) != 0;
  91}
  92#endif /* 0 */
  93
  94
  95static unsigned long
  96flash_id(unsigned char mfct, unsigned char chip)
  97{
  98  static const map_entry mfct_map[] =
  99    {
 100      {(FLASH_WORD_SIZE) AMD_MANUFACT,  (unsigned short) ((unsigned long) FLASH_MAN_AMD >> 16)},
 101      {(FLASH_WORD_SIZE) FUJ_MANUFACT,  (unsigned short) ((unsigned long) FLASH_MAN_FUJ >> 16)},
 102      {(FLASH_WORD_SIZE) STM_MANUFACT,  (unsigned short) ((unsigned long) FLASH_MAN_STM >> 16)},
 103      {(FLASH_WORD_SIZE) MT_MANUFACT,   (unsigned short) ((unsigned long) FLASH_MAN_MT >> 16)},
 104      {(FLASH_WORD_SIZE) INTEL_MANUFACT,(unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)},
 105      {(FLASH_WORD_SIZE) INTEL_ALT_MANU,(unsigned short) ((unsigned long) FLASH_MAN_INTEL >> 16)}
 106    };
 107
 108  static const map_entry chip_map[] =
 109  {
 110    {AMD_ID_F040B,      FLASH_AM040},
 111    {(FLASH_WORD_SIZE) STM_ID_x800AB,   FLASH_STM800AB}
 112  };
 113
 114  const map_entry *p;
 115  unsigned long result = FLASH_UNKNOWN;
 116
 117  /* find chip id */
 118  for(p = &chip_map[0]; p < &chip_map[sizeof chip_map / sizeof chip_map[0]]; p++)
 119    if(p->extval == chip)
 120    {
 121      result = FLASH_VENDMASK | p->intval;
 122      break;
 123    }
 124
 125  /* find vendor id */
 126  for(p = &mfct_map[0]; p < &mfct_map[sizeof mfct_map / sizeof mfct_map[0]]; p++)
 127    if(p->extval == mfct)
 128    {
 129      result &= ~FLASH_VENDMASK;
 130      result |= (unsigned long) p->intval << 16;
 131      break;
 132    }
 133
 134  return result;
 135}
 136
 137
 138unsigned long
 139flash_init(void)
 140{
 141  unsigned long i;
 142  unsigned char j;
 143  static const ulong flash_banks[] = CONFIG_SYS_FLASH_BANKS;
 144
 145  /* Init: no FLASHes known */
 146  for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
 147  {
 148    flash_info_t * const pflinfo = &flash_info[i];
 149    pflinfo->flash_id = FLASH_UNKNOWN;
 150    pflinfo->size = 0;
 151    pflinfo->sector_count = 0;
 152  }
 153
 154  /* Enable writes to Sandpoint flash */
 155  {
 156    register unsigned char temp;
 157    CONFIG_READ_BYTE(CONFIG_SYS_WINBOND_ISA_CFG_ADDR + WINBOND_CSCR, temp);
 158    temp &= ~0x20; /* clear BIOSWP bit */
 159    CONFIG_WRITE_BYTE(CONFIG_SYS_WINBOND_ISA_CFG_ADDR + WINBOND_CSCR, temp);
 160  }
 161
 162  for(i = 0; i < sizeof flash_banks / sizeof flash_banks[0]; i++)
 163  {
 164    flash_info_t * const pflinfo = &flash_info[i];
 165    const unsigned long base_address = flash_banks[i];
 166    volatile FLASH_WORD_SIZE * const flash = (FLASH_WORD_SIZE *) base_address;
 167#if 0
 168    volatile FLASH_WORD_SIZE * addr2;
 169#endif
 170#if 0
 171    /* write autoselect sequence */
 172    flash[0x5555] = 0xaa;
 173    flash[0x2aaa] = 0x55;
 174    flash[0x5555] = 0x90;
 175#else
 176    flash[0xAAA << (3 * i)] = 0xaa;
 177    flash[0x555 << (3 * i)] = 0x55;
 178    flash[0xAAA << (3 * i)] = 0x90;
 179#endif
 180    __asm__ __volatile__("sync");
 181
 182#if 0
 183    pflinfo->flash_id = flash_id(flash[0x0], flash[0x1]);
 184#else
 185    pflinfo->flash_id = flash_id(flash[0x0], flash[0x2 + 14 * i]);
 186#endif
 187
 188    switch(pflinfo->flash_id & FLASH_TYPEMASK)
 189    {
 190      case FLASH_AM040:
 191        pflinfo->size = 0x00080000;
 192        pflinfo->sector_count = 8;
 193        for(j = 0; j < 8; j++)
 194        {
 195          pflinfo->start[j] = base_address + 0x00010000 * j;
 196          pflinfo->protect[j] = flash[(j << 16) | 0x2];
 197        }
 198        break;
 199      case FLASH_STM800AB:
 200        pflinfo->size = 0x00100000;
 201        pflinfo->sector_count = 19;
 202        pflinfo->start[0] = base_address;
 203        pflinfo->start[1] = base_address + 0x4000;
 204        pflinfo->start[2] = base_address + 0x6000;
 205        pflinfo->start[3] = base_address + 0x8000;
 206        for(j = 1; j < 16; j++)
 207        {
 208          pflinfo->start[j+3] = base_address + 0x00010000 * j;
 209        }
 210#if 0
 211        /* check for protected sectors */
 212        for (j = 0; j < pflinfo->sector_count; j++) {
 213          /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 214          /* D0 = 1 if protected */
 215          addr2 = (volatile FLASH_WORD_SIZE *)(pflinfo->start[j]);
 216            if (pflinfo->flash_id & FLASH_MAN_SST)
 217              pflinfo->protect[j] = 0;
 218            else
 219              pflinfo->protect[j] = addr2[2] & 1;
 220        }
 221#endif
 222        break;
 223    }
 224    /* Protect monitor and environment sectors
 225     */
 226#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
 227    flash_protect(FLAG_PROTECT_SET,
 228                CONFIG_SYS_MONITOR_BASE,
 229                CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
 230                &flash_info[0]);
 231#endif
 232
 233#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
 234    flash_protect(FLAG_PROTECT_SET,
 235                CONFIG_ENV_ADDR,
 236                CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
 237                &flash_info[0]);
 238#endif
 239
 240    /* reset device to read mode */
 241    flash[0x0000] = 0xf0;
 242    __asm__ __volatile__("sync");
 243  }
 244
 245    return flash_info[0].size + flash_info[1].size;
 246}
 247
 248#if 0
 249static void
 250flash_get_offsets (ulong base, flash_info_t *info)
 251{
 252    int i;
 253
 254    /* set up sector start address table */
 255        if (info->flash_id & FLASH_MAN_SST)
 256          {
 257            for (i = 0; i < info->sector_count; i++)
 258              info->start[i] = base + (i * 0x00010000);
 259          }
 260        else
 261    if (info->flash_id & FLASH_BTYPE) {
 262        /* set sector offsets for bottom boot block type    */
 263        info->start[0] = base + 0x00000000;
 264        info->start[1] = base + 0x00004000;
 265        info->start[2] = base + 0x00006000;
 266        info->start[3] = base + 0x00008000;
 267        for (i = 4; i < info->sector_count; i++) {
 268            info->start[i] = base + (i * 0x00010000) - 0x00030000;
 269        }
 270    } else {
 271        /* set sector offsets for top boot block type       */
 272        i = info->sector_count - 1;
 273        info->start[i--] = base + info->size - 0x00004000;
 274        info->start[i--] = base + info->size - 0x00006000;
 275        info->start[i--] = base + info->size - 0x00008000;
 276        for (; i >= 0; i--) {
 277            info->start[i] = base + i * 0x00010000;
 278        }
 279    }
 280
 281}
 282#endif /* 0 */
 283
 284/*-----------------------------------------------------------------------
 285 */
 286void
 287flash_print_info(flash_info_t *info)
 288{
 289  static const char unk[] = "Unknown";
 290  const char *mfct = unk, *type = unk;
 291  unsigned int i;
 292
 293  if(info->flash_id != FLASH_UNKNOWN)
 294  {
 295    switch(info->flash_id & FLASH_VENDMASK)
 296    {
 297      case FLASH_MAN_AMD:       mfct = "AMD";                           break;
 298      case FLASH_MAN_FUJ:       mfct = "FUJITSU";                       break;
 299      case FLASH_MAN_STM:       mfct = "STM";                           break;
 300      case FLASH_MAN_SST:       mfct = "SST";                           break;
 301      case FLASH_MAN_BM:        mfct = "Bright Microelectonics";        break;
 302      case FLASH_MAN_INTEL:     mfct = "Intel";                         break;
 303    }
 304
 305    switch(info->flash_id & FLASH_TYPEMASK)
 306    {
 307      case FLASH_AM040:         type = "AM29F040B (512K * 8, uniform sector size)";     break;
 308      case FLASH_AM400B:        type = "AM29LV400B (4 Mbit, bottom boot sect)";         break;
 309      case FLASH_AM400T:        type = "AM29LV400T (4 Mbit, top boot sector)";          break;
 310      case FLASH_AM800B:        type = "AM29LV800B (8 Mbit, bottom boot sect)";         break;
 311      case FLASH_AM800T:        type = "AM29LV800T (8 Mbit, top boot sector)";          break;
 312      case FLASH_AM160T:        type = "AM29LV160T (16 Mbit, top boot sector)";         break;
 313      case FLASH_AM320B:        type = "AM29LV320B (32 Mbit, bottom boot sect)";        break;
 314      case FLASH_AM320T:        type = "AM29LV320T (32 Mbit, top boot sector)";         break;
 315      case FLASH_STM800AB:      type = "M29W800AB (8 Mbit, bottom boot sect)";          break;
 316      case FLASH_SST800A:       type = "SST39LF/VF800 (8 Mbit, uniform sector size)";   break;
 317      case FLASH_SST160A:       type = "SST39LF/VF160 (16 Mbit, uniform sector size)";  break;
 318    }
 319  }
 320
 321  printf(
 322    "\n  Brand: %s Type: %s\n"
 323    "  Size: %lu KB in %d Sectors\n",
 324    mfct,
 325    type,
 326    info->size >> 10,
 327    info->sector_count
 328  );
 329
 330  printf ("  Sector Start Addresses:");
 331
 332  for (i = 0; i < info->sector_count; i++)
 333  {
 334    unsigned long size;
 335    unsigned int erased;
 336    unsigned long * flash = (unsigned long *) info->start[i];
 337
 338    /*
 339     * Check if whole sector is erased
 340     */
 341    size =
 342      (i != (info->sector_count - 1)) ?
 343      (info->start[i + 1] - info->start[i]) >> 2 :
 344      (info->start[0] + info->size - info->start[i]) >> 2;
 345
 346    for(
 347      flash = (unsigned long *) info->start[i], erased = 1;
 348      (flash != (unsigned long *) info->start[i] + size) && erased;
 349      flash++
 350    )
 351      erased = *flash == ~0x0UL;
 352
 353    printf(
 354      "%s %08lX %s %s",
 355      (i % 5) ? "" : "\n   ",
 356      info->start[i],
 357      erased ? "E" : " ",
 358      info->protect[i] ? "RO" : "  "
 359    );
 360  }
 361
 362  puts("\n");
 363  return;
 364}
 365
 366#if 0
 367
 368/*
 369 * The following code cannot be run from FLASH!
 370 */
 371ulong
 372flash_get_size (vu_long *addr, flash_info_t *info)
 373{
 374   short i;
 375    FLASH_WORD_SIZE value;
 376    ulong base = (ulong)addr;
 377        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
 378
 379    printf("flash_get_size: \n");
 380    /* Write auto select command: read Manufacturer ID */
 381    eieio();
 382    addr2[ADDR0] = (FLASH_WORD_SIZE)0xAA;
 383    addr2[ADDR1] = (FLASH_WORD_SIZE)0x55;
 384    addr2[ADDR0] = (FLASH_WORD_SIZE)0x90;
 385    value = addr2[0];
 386
 387    switch (value) {
 388    case (FLASH_WORD_SIZE)AMD_MANUFACT:
 389        info->flash_id = FLASH_MAN_AMD;
 390        break;
 391    case (FLASH_WORD_SIZE)FUJ_MANUFACT:
 392        info->flash_id = FLASH_MAN_FUJ;
 393        break;
 394    case (FLASH_WORD_SIZE)SST_MANUFACT:
 395        info->flash_id = FLASH_MAN_SST;
 396        break;
 397    default:
 398        info->flash_id = FLASH_UNKNOWN;
 399        info->sector_count = 0;
 400        info->size = 0;
 401        return (0);         /* no or unknown flash  */
 402    }
 403    printf("recognised manufacturer");
 404
 405    value = addr2[ADDR3];          /* device ID        */
 406        debug ("\ndev_code=%x\n", value);
 407
 408    switch (value) {
 409    case (FLASH_WORD_SIZE)AMD_ID_LV400T:
 410        info->flash_id += FLASH_AM400T;
 411        info->sector_count = 11;
 412        info->size = 0x00080000;
 413        break;              /* => 0.5 MB        */
 414
 415    case (FLASH_WORD_SIZE)AMD_ID_LV400B:
 416        info->flash_id += FLASH_AM400B;
 417        info->sector_count = 11;
 418        info->size = 0x00080000;
 419        break;              /* => 0.5 MB        */
 420
 421    case (FLASH_WORD_SIZE)AMD_ID_LV800T:
 422        info->flash_id += FLASH_AM800T;
 423        info->sector_count = 19;
 424        info->size = 0x00100000;
 425        break;              /* => 1 MB      */
 426
 427    case (FLASH_WORD_SIZE)AMD_ID_LV800B:
 428        info->flash_id += FLASH_AM800B;
 429        info->sector_count = 19;
 430        info->size = 0x00100000;
 431        break;              /* => 1 MB      */
 432
 433    case (FLASH_WORD_SIZE)AMD_ID_LV160T:
 434        info->flash_id += FLASH_AM160T;
 435        info->sector_count = 35;
 436        info->size = 0x00200000;
 437        break;              /* => 2 MB      */
 438
 439    case (FLASH_WORD_SIZE)AMD_ID_LV160B:
 440        info->flash_id += FLASH_AM160B;
 441        info->sector_count = 35;
 442        info->size = 0x00200000;
 443        break;              /* => 2 MB      */
 444
 445    case (FLASH_WORD_SIZE)SST_ID_xF800A:
 446        info->flash_id += FLASH_SST800A;
 447        info->sector_count = 16;
 448        info->size = 0x00100000;
 449        break;              /* => 1 MB      */
 450
 451    case (FLASH_WORD_SIZE)SST_ID_xF160A:
 452        info->flash_id += FLASH_SST160A;
 453        info->sector_count = 32;
 454        info->size = 0x00200000;
 455        break;              /* => 2 MB      */
 456
 457    case (FLASH_WORD_SIZE)AMD_ID_F040B:
 458        info->flash_id += FLASH_AM040;
 459        info->sector_count = 8;
 460        info->size = 0x00080000;
 461        break;              /* => 0.5 MB      */
 462
 463    default:
 464        info->flash_id = FLASH_UNKNOWN;
 465        return (0);         /* => no or unknown flash */
 466
 467    }
 468
 469    printf("flash id %lx; sector count %x, size %lx\n", info->flash_id,info->sector_count,info->size);
 470    /* set up sector start address table */
 471        if (info->flash_id & FLASH_MAN_SST)
 472          {
 473            for (i = 0; i < info->sector_count; i++)
 474              info->start[i] = base + (i * 0x00010000);
 475          }
 476        else
 477    if (info->flash_id & FLASH_BTYPE) {
 478        /* set sector offsets for bottom boot block type    */
 479        info->start[0] = base + 0x00000000;
 480        info->start[1] = base + 0x00004000;
 481        info->start[2] = base + 0x00006000;
 482        info->start[3] = base + 0x00008000;
 483        for (i = 4; i < info->sector_count; i++) {
 484            info->start[i] = base + (i * 0x00010000) - 0x00030000;
 485        }
 486    } else {
 487        /* set sector offsets for top boot block type       */
 488        i = info->sector_count - 1;
 489        info->start[i--] = base + info->size - 0x00004000;
 490        info->start[i--] = base + info->size - 0x00006000;
 491        info->start[i--] = base + info->size - 0x00008000;
 492        for (; i >= 0; i--) {
 493            info->start[i] = base + i * 0x00010000;
 494        }
 495    }
 496
 497    /* check for protected sectors */
 498    for (i = 0; i < info->sector_count; i++) {
 499        /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 500        /* D0 = 1 if protected */
 501        addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
 502                if (info->flash_id & FLASH_MAN_SST)
 503                  info->protect[i] = 0;
 504                else
 505                  info->protect[i] = addr2[2] & 1;
 506    }
 507
 508    /*
 509     * Prevent writes to uninitialized FLASH.
 510     */
 511    if (info->flash_id != FLASH_UNKNOWN) {
 512       addr2 = (FLASH_WORD_SIZE *)info->start[0];
 513        *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
 514    }
 515
 516    return (info->size);
 517}
 518
 519#endif
 520
 521
 522int
 523flash_erase(flash_info_t *info, int s_first, int s_last)
 524{
 525    volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
 526    int flag, prot, sect, l_sect;
 527    ulong start, now, last;
 528    unsigned char sh8b;
 529
 530    if ((s_first < 0) || (s_first > s_last)) {
 531        if (info->flash_id == FLASH_UNKNOWN) {
 532            printf ("- missing\n");
 533        } else {
 534            printf ("- no sectors to erase\n");
 535        }
 536        return 1;
 537    }
 538
 539    if ((info->flash_id == FLASH_UNKNOWN) ||
 540        (info->flash_id > (FLASH_MAN_STM | FLASH_AMD_COMP))) {
 541        printf ("Can't erase unknown flash type - aborted\n");
 542        return 1;
 543    }
 544
 545    prot = 0;
 546    for (sect=s_first; sect<=s_last; ++sect) {
 547        if (info->protect[sect]) {
 548            prot++;
 549        }
 550    }
 551
 552    if (prot) {
 553        printf ("- Warning: %d protected sectors will not be erased!\n",
 554            prot);
 555    } else {
 556        printf ("\n");
 557    }
 558
 559    l_sect = -1;
 560
 561    /* Check the ROM CS */
 562    if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START))
 563      sh8b = 3;
 564    else
 565      sh8b = 0;
 566
 567    /* Disable interrupts which might cause a timeout here */
 568    flag = disable_interrupts();
 569
 570    addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
 571    addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
 572    addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
 573    addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
 574    addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
 575
 576    /* Start erase on unprotected sectors */
 577    for (sect = s_first; sect<=s_last; sect++) {
 578        if (info->protect[sect] == 0) { /* not protected */
 579            addr = (FLASH_WORD_SIZE *)(info->start[0] + (
 580                                (info->start[sect] - info->start[0]) << sh8b));
 581                        if (info->flash_id & FLASH_MAN_SST)
 582                          {
 583                            addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
 584                            addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
 585                            addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00800080;
 586                            addr[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
 587                            addr[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
 588                            addr[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
 589                            udelay(30000);  /* wait 30 ms */
 590                          }
 591                        else
 592                          addr[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
 593            l_sect = sect;
 594        }
 595    }
 596
 597    /* re-enable interrupts if necessary */
 598    if (flag)
 599        enable_interrupts();
 600
 601    /* wait at least 80us - let's wait 1 ms */
 602    udelay (1000);
 603
 604    /*
 605     * We wait for the last triggered sector
 606     */
 607    if (l_sect < 0)
 608        goto DONE;
 609
 610    start = get_timer (0);
 611    last  = start;
 612    addr = (FLASH_WORD_SIZE *)(info->start[0] + (
 613                        (info->start[l_sect] - info->start[0]) << sh8b));
 614    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
 615        if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 616            printf ("Timeout\n");
 617            return 1;
 618        }
 619        /* show that we're waiting */
 620        if ((now - last) > 1000) {  /* every second */
 621            serial_putc ('.');
 622            last = now;
 623        }
 624    }
 625
 626DONE:
 627    /* reset to read mode */
 628    addr = (FLASH_WORD_SIZE *)info->start[0];
 629    addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
 630
 631    printf (" done\n");
 632    return 0;
 633}
 634
 635/*-----------------------------------------------------------------------
 636 * Copy memory to flash, returns:
 637 * 0 - OK
 638 * 1 - write timeout
 639 * 2 - Flash not erased
 640 */
 641
 642int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 643{
 644    ulong cp, wp, data;
 645    int i, l, rc;
 646
 647    wp = (addr & ~3);   /* get lower word aligned address */
 648
 649    /*
 650     * handle unaligned start bytes
 651     */
 652    if ((l = addr - wp) != 0) {
 653        data = 0;
 654        for (i=0, cp=wp; i<l; ++i, ++cp) {
 655            data = (data << 8) | (*(uchar *)cp);
 656        }
 657        for (; i<4 && cnt>0; ++i) {
 658            data = (data << 8) | *src++;
 659            --cnt;
 660            ++cp;
 661        }
 662        for (; cnt==0 && i<4; ++i, ++cp) {
 663            data = (data << 8) | (*(uchar *)cp);
 664        }
 665
 666        if ((rc = write_word(info, wp, data)) != 0) {
 667            return (rc);
 668        }
 669        wp += 4;
 670    }
 671
 672    /*
 673     * handle word aligned part
 674     */
 675    while (cnt >= 4) {
 676        data = 0;
 677        for (i=0; i<4; ++i) {
 678            data = (data << 8) | *src++;
 679        }
 680        if ((rc = write_word(info, wp, data)) != 0) {
 681            return (rc);
 682        }
 683        wp  += 4;
 684        cnt -= 4;
 685    }
 686
 687    if (cnt == 0) {
 688        return (0);
 689    }
 690
 691    /*
 692     * handle unaligned tail bytes
 693     */
 694    data = 0;
 695    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 696        data = (data << 8) | *src++;
 697        --cnt;
 698    }
 699    for (; i<4; ++i, ++cp) {
 700        data = (data << 8) | (*(uchar *)cp);
 701    }
 702
 703    return (write_word(info, wp, data));
 704}
 705
 706/*-----------------------------------------------------------------------
 707 * Write a word to Flash, returns:
 708 * 0 - OK
 709 * 1 - write timeout
 710 * 2 - Flash not erased
 711 */
 712static int write_word (flash_info_t *info, ulong dest, ulong data)
 713{
 714        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)info->start[0];
 715        volatile FLASH_WORD_SIZE *dest2;
 716        volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
 717    ulong start;
 718    int flag;
 719        int i;
 720    unsigned char sh8b;
 721
 722    /* Check the ROM CS */
 723    if ((info->start[0] >= ROM_CS1_START) && (info->start[0] < ROM_CS0_START))
 724      sh8b = 3;
 725    else
 726      sh8b = 0;
 727
 728    dest2 = (FLASH_WORD_SIZE *)(((dest - info->start[0]) << sh8b) +
 729                                info->start[0]);
 730
 731    /* Check if Flash is (sufficiently) erased */
 732    if ((*dest2 & (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
 733        return (2);
 734    }
 735    /* Disable interrupts which might cause a timeout here */
 736    flag = disable_interrupts();
 737
 738        for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
 739          {
 740            addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00AA00AA;
 741            addr2[ADDR1 << sh8b] = (FLASH_WORD_SIZE)0x00550055;
 742            addr2[ADDR0 << sh8b] = (FLASH_WORD_SIZE)0x00A000A0;
 743
 744            dest2[i << sh8b] = data2[i];
 745
 746            /* re-enable interrupts if necessary */
 747            if (flag)
 748              enable_interrupts();
 749
 750            /* data polling for D7 */
 751            start = get_timer (0);
 752            while ((dest2[i << sh8b] & (FLASH_WORD_SIZE)0x00800080) !=
 753                   (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
 754              if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 755                return (1);
 756              }
 757            }
 758          }
 759
 760    return (0);
 761}
 762
 763/*-----------------------------------------------------------------------
 764 */
 765