uboot/board/mpc8540eval/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003 Motorola Inc.
   3 *  Xianghua Xiao,(X.Xiao@motorola.com)
   4 *
   5 * (C) Copyright 2000, 2001
   6 *  Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   7 *
   8 * (C) Copyright 2001, Stuart Hughes, Lineo Inc, stuarth@lineo.com
   9 * Add support the Sharp chips on the mpc8260ads.
  10 * I started with board/ip860/flash.c and made changes I found in
  11 * the MTD project by David Schleef.
  12 *
  13 * See file CREDITS for list of people who contributed to this
  14 * project.
  15 *
  16 * This program is free software; you can redistribute it and/or
  17 * modify it under the terms of the GNU General Public License as
  18 * published by the Free Software Foundation; either version 2 of
  19 * the License, or (at your option) any later version.
  20 *
  21 * This program is distributed in the hope that it will be useful,
  22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24 * GNU General Public License for more details.
  25 *
  26 * You should have received a copy of the GNU General Public License
  27 * along with this program; if not, write to the Free Software
  28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  29 * MA 02111-1307 USA
  30 */
  31
  32#include <common.h>
  33
  34#if !defined(CONFIG_SYS_NO_FLASH)
  35
  36flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  37
  38#if defined(CONFIG_ENV_IS_IN_FLASH)
  39# ifndef  CONFIG_ENV_ADDR
  40#  define CONFIG_ENV_ADDR       (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
  41# endif
  42# ifndef  CONFIG_ENV_SIZE
  43#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
  44# endif
  45# ifndef  CONFIG_ENV_SECT_SIZE
  46#  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
  47# endif
  48#endif
  49
  50/*
  51 * The variable should be in the flash info structure. Since it
  52 * is only used in this board specific file it is declared here.
  53 * In the future I think an endian flag should be part of the
  54 * flash_info_t structure. (Ron Alder)
  55 */
  56static ulong big_endian = 0;
  57
  58/*-----------------------------------------------------------------------
  59 * Functions
  60 */
  61static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  62static int write_block (flash_info_t *info, uchar * src, ulong dest, ulong cnt);
  63static int write_short (flash_info_t *info, ulong dest, ushort data);
  64static int write_word (flash_info_t *info, ulong dest, ulong data);
  65static int clear_block_lock_bit(flash_info_t *info, vu_long * addr);
  66/*-----------------------------------------------------------------------
  67 */
  68
  69unsigned long flash_init (void)
  70{
  71        unsigned long size;
  72        int i;
  73
  74        /* Init: enable write,
  75         * or we cannot even write flash commands
  76         */
  77        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  78                flash_info[i].flash_id = FLASH_UNKNOWN;
  79
  80                /* set the default sector offset */
  81        }
  82
  83        /* Static FLASH Bank configuration here - FIXME XXX */
  84
  85        size = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  86
  87        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
  88                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
  89                        size, size<<20);
  90        }
  91
  92        /* Re-do sizing to get full correct info */
  93        size = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  94
  95        flash_info[0].size = size;
  96
  97#if !defined(CONFIG_RAM_AS_FLASH)
  98#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  99        /* monitor protection ON by default */
 100        flash_protect(FLAG_PROTECT_SET,
 101                      CONFIG_SYS_MONITOR_BASE,
 102                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
 103                      &flash_info[0]);
 104#endif
 105
 106#ifdef  CONFIG_ENV_IS_IN_FLASH
 107        /* ENV protection ON by default */
 108        flash_protect(FLAG_PROTECT_SET,
 109                      CONFIG_ENV_ADDR,
 110                      CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
 111                      &flash_info[0]);
 112#endif
 113#endif
 114        return (size);
 115}
 116
 117/*-----------------------------------------------------------------------
 118 */
 119void flash_print_info  (flash_info_t *info)
 120{
 121        int i;
 122
 123        if (info->flash_id == FLASH_UNKNOWN) {
 124                printf ("missing or unknown FLASH type\n");
 125                return;
 126        }
 127
 128        switch (info->flash_id & FLASH_VENDMASK) {
 129        case FLASH_MAN_INTEL:   printf ("Intel ");              break;
 130        case FLASH_MAN_SHARP:   printf ("Sharp ");              break;
 131        default:                printf ("Unknown Vendor ");     break;
 132        }
 133
 134        switch (info->flash_id & FLASH_TYPEMASK) {
 135        case FLASH_28F016SV:    printf ("28F016SV (16 Mbit, 32 x 64k)\n");
 136                                break;
 137        case FLASH_28F160S3:    printf ("28F160S3 (16 Mbit, 32 x 512K)\n");
 138                                break;
 139        case FLASH_28F320S3:    printf ("28F320S3 (32 Mbit, 64 x 512K)\n");
 140                                break;
 141        case FLASH_LH28F016SCT: printf ("28F016SC (16 Mbit, 32 x 64K)\n");
 142                                break;
 143        case FLASH_28F640J3A:   printf ("28F640J3A (64 Mbit, 64 x 128K)\n");
 144                                break;
 145        default:                printf ("Unknown Chip Type\n");
 146                                break;
 147        }
 148
 149        printf ("  Size: %ld MB in %d Sectors\n",
 150                info->size >> 20, info->sector_count);
 151
 152        printf ("  Sector Start Addresses:");
 153        for (i=0; i<info->sector_count; ++i) {
 154                if ((i % 5) == 0)
 155                        printf ("\n   ");
 156                printf (" %08lX%s",
 157                        info->start[i],
 158                        info->protect[i] ? " (RO)" : "     "
 159                );
 160        }
 161        printf ("\n");
 162}
 163
 164 /* only deal with 16 bit and 32 bit port width, 16bit chip */
 165static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 166{
 167        short i;
 168        ulong value,va,vb,vc,vd;
 169        ulong base = (ulong)addr;
 170        ulong sector_offset;
 171
 172#ifdef DEBUG
 173        printf("Check flash at 0x%08x\n",(uint)addr);
 174#endif
 175        /* Write "Intelligent Identifier" command: read Manufacturer ID */
 176        *addr = 0x90909090;
 177        udelay(20);
 178        asm("sync");
 179
 180#ifndef CONFIG_SYS_FLASH_CFI
 181        printf("Not define CONFIG_SYS_FLASH_CFI\n");
 182        return (0);
 183#else
 184        value = addr[0];
 185        va=(value & 0xFF000000)>>24;
 186        vb=(value & 0x00FF0000)>>16;
 187        vc=(value & 0x0000FF00)>>8;
 188        vd=(value & 0x000000FF);
 189        if ((va==0) && (vb==0)) {
 190                printf("cannot identify Flash\n");
 191                info->flash_id = FLASH_UNKNOWN;
 192                info->sector_count = 0;
 193                info->size = 0;
 194                return (0);                     /* no or unknown flash  */
 195        }
 196        else if ((va==0) && (vb!=0)) {
 197                big_endian = 1;
 198                info->chipwidth = FLASH_CFI_BY16;
 199                if(vb == vd) info->portwidth = FLASH_CFI_32BIT;
 200                else info->portwidth = FLASH_CFI_16BIT;
 201        }
 202        else if ((va!=0) && (vb==0)) {
 203                big_endian = 0;
 204                info->chipwidth = FLASH_CFI_BY16;
 205                if(va == vc) info->portwidth = FLASH_CFI_32BIT;
 206                else info->portwidth = FLASH_CFI_16BIT;
 207        }
 208        else if ((va!=0) && (vb!=0)) {
 209                big_endian = 1;         /* no meaning for 8bit chip */
 210                info->chipwidth = FLASH_CFI_BY8;
 211                if(va == vb) info->portwidth = FLASH_CFI_16BIT;
 212                else info->portwidth = FLASH_CFI_8BIT;
 213        }
 214#ifdef DEBUG
 215        switch (info->portwidth) {
 216                case FLASH_CFI_8BIT:
 217                        printf("port width is 8 bit.\n");
 218                        break;
 219                case FLASH_CFI_16BIT:
 220                        printf("port width is 16 bit, ");
 221                        break;
 222                case FLASH_CFI_32BIT:
 223                        printf("port width is 32 bit, ");
 224                        break;
 225        }
 226        switch (info->chipwidth) {
 227                case FLASH_CFI_BY16:
 228                        printf("chip width is 16 bit, ");
 229                        switch (big_endian) {
 230                                case 0:
 231                                        printf("Little Endian.\n");
 232                                        break;
 233                                case 1:
 234                                        printf("Big Endian.\n");
 235                                        break;
 236                        }
 237                        break;
 238        }
 239#endif
 240#endif          /*#ifdef CONFIG_SYS_FLASH_CFI*/
 241
 242        if (big_endian==0) value = (addr[0] & 0xFF000000) >>8;
 243        else value = (addr[0] & 0x00FF0000);
 244#ifdef DEBUG
 245        printf("manufacturer=0x%x\n",(uint)(value>>16));
 246#endif
 247        switch (value) {
 248        case MT_MANUFACT & 0xFFFF0000:  /* SHARP, MT or => Intel */
 249        case INTEL_ALT_MANU & 0xFFFF0000:
 250                info->flash_id = FLASH_MAN_INTEL;
 251                break;
 252        default:
 253                printf("unknown manufacturer: %x\n", (unsigned int)value);
 254                info->flash_id = FLASH_UNKNOWN;
 255                info->sector_count = 0;
 256                info->size = 0;
 257                return (0);                     /* no or unknown flash  */
 258        }
 259
 260        if (info->portwidth==FLASH_CFI_16BIT) {
 261                switch (big_endian) {
 262                        case 0:
 263                                value = (addr[0] & 0x0000FF00)>>8;
 264                                break;
 265                        case 1:
 266                                value = (addr[0] & 0x000000FF);
 267                                break;
 268                }
 269        }
 270        else if (info->portwidth == FLASH_CFI_32BIT) {
 271                switch (big_endian) {
 272                        case 0:
 273                                value = (addr[1] & 0x0000FF00)>>8;
 274                                break;
 275                        case 1:
 276                                value = (addr[1] & 0x000000FF);
 277                                break;
 278                }
 279        }
 280
 281#ifdef DEBUG
 282        printf("deviceID=0x%x\n",(uint)value);
 283#endif
 284        switch (value) {
 285        case (INTEL_ID_28F016S & 0x0000FFFF):
 286                info->flash_id += FLASH_28F016SV;
 287                info->sector_count = 32;
 288                sector_offset = 0x10000;
 289                break;                          /* => 2 MB              */
 290
 291        case (INTEL_ID_28F160S3 & 0x0000FFFF):
 292                info->flash_id += FLASH_28F160S3;
 293                info->sector_count = 32;
 294                sector_offset = 0x10000;
 295                break;                          /* => 2 MB              */
 296
 297        case (INTEL_ID_28F320S3 & 0x0000FFFF):
 298                info->flash_id += FLASH_28F320S3;
 299                info->sector_count = 64;
 300                sector_offset = 0x10000;
 301                break;                          /* => 4 MB              */
 302
 303        case (INTEL_ID_28F640J3A & 0x0000FFFF):
 304                info->flash_id += FLASH_28F640J3A;
 305                info->sector_count = 64;
 306                sector_offset = 0x20000;
 307                break;                          /* => 8 MB             */
 308
 309        case SHARP_ID_28F016SCL & 0x0000FFFF:
 310        case SHARP_ID_28F016SCZ & 0x0000FFFF:
 311                info->flash_id      = FLASH_MAN_SHARP | FLASH_LH28F016SCT;
 312                info->sector_count  = 32;
 313                sector_offset = 0x10000;
 314                break;                          /* => 2 MB              */
 315
 316
 317        default:
 318                info->flash_id = FLASH_UNKNOWN;
 319                return (0);                     /* => no or unknown flash */
 320
 321        }
 322
 323        sector_offset = sector_offset * (info->portwidth / info->chipwidth);
 324        info->size = info->sector_count * sector_offset;
 325
 326        /* set up sector start address table */
 327        for (i = 0; i < info->sector_count; i++) {
 328                info->start[i] = base;
 329                base += sector_offset;
 330                /* don't know how to check sector protection */
 331                info->protect[i] = 0;
 332        }
 333
 334        /*
 335         * Prevent writes to uninitialized FLASH.
 336         */
 337        if (info->flash_id != FLASH_UNKNOWN) {
 338                addr = (vu_long *)info->start[0];
 339                *addr = 0xFFFFFF;       /* reset bank to read array mode */
 340                asm("sync");
 341        }
 342
 343        return (info->size);
 344}
 345
 346
 347/*-----------------------------------------------------------------------
 348 */
 349
 350int     flash_erase (flash_info_t *info, int s_first, int s_last)
 351{
 352        int flag, prot, sect;
 353        ulong start, now, last, ready, erase_err_status;
 354
 355        if (big_endian == 1) {
 356                ready = 0x0080;
 357                erase_err_status = 0x00a0;
 358        }
 359        else {
 360                ready = 0x8000;
 361                erase_err_status = 0xa000;
 362        }
 363        if ((info->portwidth / info->chipwidth)==2) {
 364                ready += (ready <<16);
 365                erase_err_status += (erase_err_status <<16);
 366        }
 367
 368#ifdef DEBUG
 369        printf ("\nReady flag is 0x%lx\nErase error flag is 0x%lx", ready, erase_err_status);
 370#endif
 371
 372        if ((s_first < 0) || (s_first > s_last)) {
 373                if (info->flash_id == FLASH_UNKNOWN) {
 374                        printf ("- missing\n");
 375                } else {
 376                        printf ("- no sectors to erase\n");
 377                }
 378                return 1;
 379        }
 380
 381        if (    ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL)
 382             && ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_SHARP) ) {
 383                printf ("Can't erase unknown flash type %08lx - aborted\n",
 384                        info->flash_id);
 385                return 1;
 386        }
 387
 388        prot = 0;
 389        for (sect=s_first; sect<=s_last; ++sect) {
 390                if (info->protect[sect]) {
 391                        prot++;
 392                }
 393        }
 394
 395        if (prot) {
 396                printf ("- Warning: %d protected sectors will not be erased!\n",
 397                        prot);
 398        } else {
 399                printf ("\n");
 400        }
 401
 402#ifdef DEBUG
 403        printf("\nFlash Erase:\n");
 404#endif
 405        /* Make Sure Block Lock Bit is not set. */
 406        if(clear_block_lock_bit(info, (vu_long *)(info->start[s_first]))){
 407                return 1;
 408        }
 409
 410        /* Start erase on unprotected sectors */
 411#if defined(DEBUG)
 412        printf("Begin to erase now,s_first=0x%x s_last=0x%x...\n",s_first,s_last);
 413#endif
 414        for (sect = s_first; sect<=s_last; sect++) {
 415                if (info->protect[sect] == 0) { /* not protected */
 416                        vu_short *addr16 = (vu_short *)(info->start[sect]);
 417                        vu_long *addr   = (vu_long *)(info->start[sect]);
 418                        printf(".");
 419                        switch (info->portwidth) {
 420                                case FLASH_CFI_16BIT:
 421                                        asm("sync");
 422                                        last = start = get_timer (0);
 423                                        /* Disable interrupts which might cause a timeout here */
 424                                        flag = disable_interrupts();
 425                                        /* Reset Array */
 426                                        *addr16 = 0xffff;
 427                                        asm("sync");
 428                                        /* Clear Status Register */
 429                                        *addr16 = 0x5050;
 430                                        asm("sync");
 431                                        /* Single Block Erase Command */
 432                                        *addr16 = 0x2020;
 433                                        asm("sync");
 434                                        /* Confirm */
 435                                        *addr16 = 0xD0D0;
 436                                        asm("sync");
 437                                        if((info->flash_id & FLASH_TYPEMASK) != FLASH_LH28F016SCT) {
 438                                            /* Resume Command, as per errata update */
 439                                            *addr16 = 0xD0D0;
 440                                            asm("sync");
 441                                        }
 442                                        /* re-enable interrupts if necessary */
 443                                        if (flag)
 444                                                enable_interrupts();
 445                                        /* wait at least 80us - let's wait 1 ms */
 446                                        *addr16 = 0x7070;
 447                                        udelay (1000);
 448                                        while ((*addr16 & ready) != ready) {
 449                                                if((*addr16 & erase_err_status)== erase_err_status){
 450                                                        printf("Error in Block Erase - Lock Bit may be set!\n");
 451                                                        printf("Status Register = 0x%X\n", (uint)*addr16);
 452                                                        *addr16 = 0xFFFF;       /* reset bank */
 453                                                        asm("sync");
 454                                                        return 1;
 455                                                }
 456                                                if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 457                                                        printf ("Timeout\n");
 458                                                        *addr16 = 0xFFFF;       /* reset bank */
 459                                                        asm("sync");
 460                                                        return 1;
 461                                                }
 462                                                /* show that we're waiting */
 463                                                if ((now - last) > 1000) {      /* every second */
 464                                                        putc ('.');
 465                                                        last = now;
 466                                                }
 467                                        }
 468                                        /* reset to read mode */
 469                                        *addr16 = 0xFFFF;
 470                                        asm("sync");
 471                                        break;
 472                                case FLASH_CFI_32BIT:
 473                                        asm("sync");
 474                                        last = start = get_timer (0);
 475                                        /* Disable interrupts which might cause a timeout here */
 476                                        flag = disable_interrupts();
 477                                        /* Reset Array */
 478                                        *addr = 0xffffffff;
 479                                        asm("sync");
 480                                        /* Clear Status Register */
 481                                        *addr = 0x50505050;
 482                                        asm("sync");
 483                                        /* Single Block Erase Command */
 484                                        *addr = 0x20202020;
 485                                        asm("sync");
 486                                        /* Confirm */
 487                                        *addr = 0xD0D0D0D0;
 488                                        asm("sync");
 489                                        if((info->flash_id & FLASH_TYPEMASK) != FLASH_LH28F016SCT) {
 490                                            /* Resume Command, as per errata update */
 491                                            *addr = 0xD0D0D0D0;
 492                                            asm("sync");
 493                                        }
 494                                        /* re-enable interrupts if necessary */
 495                                        if (flag)
 496                                                enable_interrupts();
 497                                        /* wait at least 80us - let's wait 1 ms */
 498                                        *addr = 0x70707070;
 499                                        udelay (1000);
 500                                        while ((*addr & ready) != ready) {
 501                                                if((*addr & erase_err_status)==erase_err_status){
 502                                                        printf("Error in Block Erase - Lock Bit may be set!\n");
 503                                                        printf("Status Register = 0x%X\n", (uint)*addr);
 504                                                        *addr = 0xFFFFFFFF;     /* reset bank */
 505                                                        asm("sync");
 506                                                        return 1;
 507                                                }
 508                                                if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 509                                                        printf ("Timeout\n");
 510                                                        *addr = 0xFFFFFFFF;     /* reset bank */
 511                                                        asm("sync");
 512                                                        return 1;
 513                                                }
 514                                                /* show that we're waiting */
 515                                                if ((now - last) > 1000) {      /* every second */
 516                                                        putc ('.');
 517                                                        last = now;
 518                                                }
 519                                        }
 520                                        /* reset to read mode */
 521                                        *addr = 0xFFFFFFFF;
 522                                        asm("sync");
 523                                        break;
 524                        }       /* end switch */
 525                }               /* end if */
 526        }                       /* end for */
 527
 528        printf ("flash erase done\n");
 529        return 0;
 530}
 531
 532/*-----------------------------------------------------------------------
 533 * Copy memory to flash, returns:
 534 * 0 - OK
 535 * 1 - write timeout
 536 * 2 - Flash not erased
 537 */
 538
 539#define FLASH_BLOCK_SIZE 32
 540
 541int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 542{
 543        ulong cp, wp, data, count, temp;
 544/*      ulong temp[FLASH_BLOCK_SIZE/4];*/
 545        int i, l, rc;
 546
 547        count = cnt;
 548        wp = (addr & ~3);       /* get lower word aligned address */
 549
 550        /*
 551         * handle unaligned start bytes
 552         */
 553        if ((l = addr - wp) != 0) {
 554                data = 0;
 555                for (i=0, cp=wp; i<l; ++i, ++cp) {
 556                        data = (data << 8) | (*(uchar *)cp);
 557                }
 558                for (; i<4 && cnt>0; ++i) {
 559                        data = (data << 8) | *src++;
 560                        --cnt;
 561                        ++cp;
 562                }
 563                for (; cnt==0 && i<4; ++i, ++cp) {
 564                        data = (data << 8) | (*(uchar *)cp);
 565                }
 566
 567                if ((rc = write_word(info, wp, data)) != 0) {
 568                        return (rc);
 569                }
 570                wp += 4;
 571        }
 572
 573        cp = wp;
 574        /* handle unaligned block bytes , flash block size = 16bytes */
 575        wp = (cp+FLASH_BLOCK_SIZE-1) & ~(FLASH_BLOCK_SIZE-1);
 576        if ((wp-cp)>=cnt) {
 577                if ((rc = write_block(info,src,cp,wp-cp)) !=0)
 578                        return (rc);
 579                src += wp-cp;
 580                cnt -= wp-cp;
 581        }
 582        /* handle aligned block bytes */
 583        temp = 0;
 584        printf("\n");
 585        while ( cnt >= FLASH_BLOCK_SIZE) {
 586                if ((rc = write_block(info,src,cp,FLASH_BLOCK_SIZE)) !=0) {
 587                        return (rc);
 588                }
 589                src += FLASH_BLOCK_SIZE;
 590                cp += FLASH_BLOCK_SIZE;
 591                cnt -= FLASH_BLOCK_SIZE;
 592                if (((count-cnt)>>10)>temp) {
 593                        temp=(count-cnt)>>10;
 594                        printf("\r%lu KB",temp);
 595                }
 596        }
 597        printf("\n");
 598        wp = cp;
 599        /*
 600         * handle word aligned part
 601         */
 602        while (cnt >= 4) {
 603                data = 0;
 604                for (i=0; i<4; ++i) {
 605                        data = (data << 8) | *src++;
 606                }
 607                if ((rc = write_word(info, wp, data)) != 0) {
 608                        return (rc);
 609                }
 610                wp  += 4;
 611                cnt -= 4;
 612        }
 613
 614        if (cnt == 0) {
 615                return (0);
 616        }
 617
 618        /*
 619         * handle unaligned tail bytes
 620         */
 621        data = 0;
 622        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 623                data = (data << 8) | *src++;
 624                --cnt;
 625        }
 626        for (; i<4; ++i, ++cp) {
 627                data = (data << 8) | (*(uchar *)cp);
 628        }
 629
 630        return (write_word(info, wp, data));
 631}
 632#undef FLASH_BLOCK_SIZE
 633
 634/*-----------------------------------------------------------------------
 635 * Write block to Flash, returns:
 636 * 0 - OK
 637 * 1 - write timeout
 638 * 2 - Flash not erased
 639 * -1  Error
 640 */
 641static int write_block(flash_info_t *info, uchar * src, ulong dest, ulong cnt)
 642{
 643        vu_short *baddr, *addr = (vu_short *)dest;
 644        ushort data;
 645        ulong start, now, xsr,csr, ready;
 646        int flag;
 647
 648        if (cnt==0) return 0;
 649        else if(cnt != (cnt& ~1)) return -1;
 650
 651        /* Check if Flash is (sufficiently) erased */
 652        data = * src;
 653        data = (data<<8) | *(src+1);
 654        if ((*addr & data) != data) {
 655                return (2);
 656        }
 657        if (big_endian == 1) {
 658                ready = 0x0080;
 659        }
 660        else {
 661                ready = 0x8000;
 662        }
 663        /* Disable interrupts which might cause a timeout here */
 664        flag = disable_interrupts();
 665
 666                do {
 667                        /* Write Command */
 668                        *addr = 0xe8e8;
 669                        asm("sync");
 670                        xsr = *addr;
 671                        asm("sync");
 672                } while (!(xsr & ready));       /*wait until read */
 673                /*write count=BLOCK SIZE -1 */
 674                data=(cnt>>1)-1;
 675                data=(data<<8)|data;
 676                *addr = data;           /* word mode, cnt/2 */
 677                asm("sync");
 678                baddr = addr;
 679                while(cnt) {
 680                        data = * src++;
 681                        data = (data<<8) | *src++;
 682                        asm("sync");
 683                        *baddr = data;
 684                        asm("sync");
 685                        ++baddr;
 686                        cnt = cnt -2;
 687                }
 688                *addr = 0xd0d0;                 /* confirm write */
 689                start = get_timer(0);
 690                asm("sync");
 691                if (flag)
 692                        enable_interrupts();
 693                /* data polling for D7 */
 694                flag  = 0;
 695                while (((csr = *addr) & ready) != ready) {
 696                        if ((now=get_timer(start)) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 697                                flag = 1;
 698                                break;
 699                        }
 700                }
 701                if (csr & 0x4040) {
 702                        printf ("CSR indicates write error (%04lx) at %08lx\n",
 703                                csr, (ulong)addr);
 704                        flag = 1;
 705                }
 706                /* Clear Status Registers Command */
 707                *addr = 0x5050;
 708                asm("sync");
 709                /* Reset to read array mode */
 710                *addr = 0xFFFF;
 711                asm("sync");
 712        return (flag);
 713}
 714
 715
 716/*-----------------------------------------------------------------------
 717 * Write a short word to Flash, returns:
 718 * 0 - OK
 719 * 1 - write timeout
 720 * 2 - Flash not erased
 721 */
 722static int write_short (flash_info_t *info, ulong dest, ushort data)
 723{
 724        vu_short *addr = (vu_short *)dest;
 725        ulong start, now, csr, ready;
 726        int flag;
 727
 728        /* Check if Flash is (sufficiently) erased */
 729        if ((*addr & data) != data) {
 730                return (2);
 731        }
 732        /* Disable interrupts which might cause a timeout here */
 733        flag = disable_interrupts();
 734
 735                /* Write Command */
 736                *addr = 0x1010;
 737                start = get_timer (0);
 738                asm("sync");
 739                /* Write Data */
 740                *addr = data;
 741                asm("sync");
 742                /* re-enable interrupts if necessary */
 743                if (flag)
 744                        enable_interrupts();
 745                if (big_endian == 1) {
 746                        ready = 0x0080;
 747                }
 748                else {
 749                        ready = 0x8000;
 750                }
 751                /* data polling for D7 */
 752                flag  = 0;
 753                while (((csr = *addr) & ready) != ready) {
 754                        if ((now=get_timer(start)) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 755                                flag = 1;
 756                                break;
 757                        }
 758                }
 759                if (csr & 0x4040) {
 760                        printf ("CSR indicates write error (%04lx) at %08lx\n",
 761                                csr, (ulong)addr);
 762                        flag = 1;
 763                }
 764                /* Clear Status Registers Command */
 765                *addr = 0x5050;
 766                asm("sync");
 767                /* Reset to read array mode */
 768                *addr = 0xFFFF;
 769                asm("sync");
 770        return (flag);
 771}
 772
 773/*-----------------------------------------------------------------------
 774 * Write a word to Flash, returns:
 775 * 0 - OK
 776 * 1 - write timeout
 777 * 2 - Flash not erased
 778 */
 779static int write_word (flash_info_t *info, ulong dest, ulong data)
 780{
 781        vu_long *addr = (vu_long *)dest;
 782        ulong start, csr, ready;
 783        int flag=0;
 784
 785        switch (info->portwidth) {
 786        case FLASH_CFI_32BIT:
 787                /* Check if Flash is (sufficiently) erased */
 788                if ((*addr & data) != data) {
 789                        return (2);
 790                }
 791                /* Disable interrupts which might cause a timeout here */
 792                flag = disable_interrupts();
 793
 794                if (big_endian == 1) {
 795                        ready = 0x0080;
 796                }
 797                else {
 798                        ready = 0x8000;
 799                }
 800                if ((info->portwidth / info->chipwidth)==2) {
 801                        ready += (ready <<16);
 802                }
 803                else {
 804                        ready = ready << 16;
 805                }
 806                /* Write Command */
 807                *addr = 0x10101010;
 808                asm("sync");
 809                /* Write Data */
 810                *addr = data;
 811                /* re-enable interrupts if necessary */
 812                if (flag)
 813                        enable_interrupts();
 814                /* data polling for D7 */
 815                start = get_timer (0);
 816                flag  = 0;
 817                while (((csr = *addr) & ready) != ready) {
 818                        if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 819                                flag = 1;
 820                                break;
 821                        }
 822                }
 823                if (csr & 0x40404040) {
 824                        printf ("CSR indicates write error (%08lx) at %08lx\n", csr, (ulong)addr);
 825                        flag = 1;
 826                }
 827                /* Clear Status Registers Command */
 828                *addr = 0x50505050;
 829                asm("sync");
 830                /* Reset to read array mode */
 831                *addr = 0xFFFFFFFF;
 832                asm("sync");
 833                break;
 834        case FLASH_CFI_16BIT:
 835                flag = write_short (info, dest,  (unsigned short) (data>>16));
 836                if (flag == 0)
 837                        flag = write_short (info, dest+2,  (unsigned short) (data));
 838                break;
 839        }
 840        return (flag);
 841}
 842
 843/*-----------------------------------------------------------------------
 844 * Clear Block Lock Bit, returns:
 845 * 0 - OK
 846 * 1 - Timeout
 847 */
 848
 849static int clear_block_lock_bit(flash_info_t * info, vu_long  * addr)
 850{
 851        ulong start, now, ready;
 852
 853        /* Reset Array */
 854        *addr = 0xffffffff;
 855        asm("sync");
 856        /* Clear Status Register */
 857        *addr = 0x50505050;
 858        asm("sync");
 859
 860        *addr = 0x60606060;
 861        asm("sync");
 862        *addr = 0xd0d0d0d0;
 863        asm("sync");
 864
 865
 866        if (big_endian == 1) {
 867                ready = 0x0080;
 868        }
 869        else {
 870                ready = 0x8000;
 871        }
 872        if ((info->portwidth / info->chipwidth)==2) {
 873                ready += (ready <<16);
 874        }
 875        else {
 876                ready = ready << 16;
 877        }
 878#ifdef DEBUG
 879        printf ("%s: Ready flag is 0x%8lx\n", __FUNCTION__, ready);
 880#endif
 881        *addr = 0x70707070;     /* read status */
 882        start = get_timer (0);
 883        while((*addr & ready) != ready){
 884                if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 885                        printf ("Timeout on clearing Block Lock Bit\n");
 886                        *addr = 0xFFFFFFFF;     /* reset bank */
 887                        asm("sync");
 888                        return 1;
 889                }
 890        }
 891        return 0;
 892}
 893
 894#endif /* !CONFIG_SYS_NO_FLASH */
 895