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