uboot/tools/updater/flash_hw.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
   4 *
   5 * (C) Copyright 2002
   6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27#include <common.h>
  28#include <flash.h>
  29#include <asm/io.h>
  30#include <memio.h>
  31
  32/*---------------------------------------------------------------------*/
  33#undef DEBUG_FLASH
  34
  35#ifdef DEBUG_FLASH
  36#define DEBUGF(fmt,args...) printf(fmt ,##args)
  37#else
  38#define DEBUGF(fmt,args...)
  39#endif
  40/*---------------------------------------------------------------------*/
  41
  42flash_info_t    flash_info[];
  43
  44static ulong flash_get_size (ulong addr, flash_info_t *info);
  45static int flash_get_offsets (ulong base, flash_info_t *info);
  46static int write_word (flash_info_t *info, ulong dest, ulong data);
  47static void flash_reset (ulong addr);
  48
  49int flash_xd_nest;
  50
  51static void flash_to_xd(void)
  52{
  53    unsigned char x;
  54
  55    flash_xd_nest ++;
  56
  57    if (flash_xd_nest == 1)
  58    {
  59        DEBUGF("Flash on XD\n");
  60        x = pci_read_cfg_byte(0, 0, 0x74);
  61        pci_write_cfg_byte(0, 0, 0x74, x|1);
  62    }
  63}
  64
  65static void flash_to_mem(void)
  66{
  67    unsigned char x;
  68
  69    flash_xd_nest --;
  70
  71    if (flash_xd_nest == 0)
  72    {
  73        DEBUGF("Flash on memory bus\n");
  74        x = pci_read_cfg_byte(0, 0, 0x74);
  75        pci_write_cfg_byte(0, 0, 0x74, x&0xFE);
  76    }
  77}
  78
  79unsigned long flash_init_old(void)
  80{
  81    int i;
  82
  83    for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
  84    {
  85        flash_info[i].flash_id = FLASH_UNKNOWN;
  86        flash_info[i].sector_count = 0;
  87        flash_info[i].size = 0;
  88    }
  89
  90
  91    return 1;
  92}
  93
  94unsigned long flash_init (void)
  95{
  96        unsigned int i;
  97        unsigned long flash_size = 0;
  98
  99        flash_xd_nest = 0;
 100
 101        flash_to_xd();
 102
 103        /* Init: no FLASHes known */
 104        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
 105                flash_info[i].flash_id = FLASH_UNKNOWN;
 106                flash_info[i].sector_count = 0;
 107                flash_info[i].size = 0;
 108        }
 109
 110        DEBUGF("\n## Get flash size @ 0x%08x\n", CONFIG_SYS_FLASH_BASE);
 111
 112        flash_size = flash_get_size (CONFIG_SYS_FLASH_BASE, flash_info);
 113
 114        DEBUGF("## Flash bank size: %08lx\n", flash_size);
 115
 116        if (flash_size) {
 117#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE && \
 118    CONFIG_SYS_MONITOR_BASE < CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_MAX_SIZE
 119                /* monitor protection ON by default */
 120                flash_protect(FLAG_PROTECT_SET,
 121                              CONFIG_SYS_MONITOR_BASE,
 122                              CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
 123                              &flash_info[0]);
 124#endif
 125
 126#ifdef CONFIG_ENV_IS_IN_FLASH
 127                /* ENV protection ON by default */
 128                flash_protect(FLAG_PROTECT_SET,
 129                              CONFIG_ENV_ADDR,
 130                              CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
 131                              &flash_info[0]);
 132#endif
 133
 134        } else {
 135                printf ("Warning: the BOOT Flash is not initialised !");
 136        }
 137
 138        flash_to_mem();
 139
 140        return flash_size;
 141}
 142
 143/*
 144 * The following code cannot be run from FLASH!
 145 */
 146static ulong flash_get_size (ulong addr, flash_info_t *info)
 147{
 148        short i;
 149        uchar value;
 150        uchar *x = (uchar *)addr;
 151
 152        flash_to_xd();
 153
 154        /* Write auto select command: read Manufacturer ID */
 155        x[0x0555] =  0xAA;
 156        __asm__ volatile ("sync\n eieio");
 157        x[0x02AA] =  0x55;
 158        __asm__ volatile ("sync\n eieio");
 159        x[0x0555] =  0x90;
 160        __asm__ volatile ("sync\n eieio");
 161
 162        value = x[0];
 163        __asm__ volatile ("sync\n eieio");
 164
 165        DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (ulong)addr, value);
 166
 167        switch (value | (value << 16)) {
 168                case AMD_MANUFACT:
 169                        info->flash_id = FLASH_MAN_AMD;
 170                        break;
 171
 172                case FUJ_MANUFACT:
 173                        info->flash_id = FLASH_MAN_FUJ;
 174                        break;
 175
 176                case STM_MANUFACT:
 177                        info->flash_id = FLASH_MAN_STM;
 178                        break;
 179
 180                default:
 181                        info->flash_id = FLASH_UNKNOWN;
 182                        info->sector_count = 0;
 183                        info->size = 0;
 184                        flash_reset (addr);
 185                        return 0;
 186        }
 187
 188        value = x[1];
 189        __asm__ volatile ("sync\n eieio");
 190
 191        DEBUGF("Device ID @ 0x%08lx: 0x%08x\n", addr+1, value);
 192
 193        switch (value) {
 194                case AMD_ID_F040B:
 195                        DEBUGF("Am29F040B\n");
 196                        info->flash_id += FLASH_AM040;
 197                        info->sector_count = 8;
 198                        info->size = 0x00080000;
 199                        break;                  /* => 512 kB            */
 200
 201                case AMD_ID_LV040B:
 202                        DEBUGF("Am29LV040B\n");
 203                        info->flash_id += FLASH_AM040;
 204                        info->sector_count = 8;
 205                        info->size = 0x00080000;
 206                        break;                  /* => 512 kB            */
 207
 208                case AMD_ID_LV400T:
 209                        DEBUGF("Am29LV400T\n");
 210                        info->flash_id += FLASH_AM400T;
 211                        info->sector_count = 11;
 212                        info->size = 0x00100000;
 213                        break;                  /* => 1 MB              */
 214
 215                case AMD_ID_LV400B:
 216                        DEBUGF("Am29LV400B\n");
 217                        info->flash_id += FLASH_AM400B;
 218                        info->sector_count = 11;
 219                        info->size = 0x00100000;
 220                        break;                  /* => 1 MB              */
 221
 222                case AMD_ID_LV800T:
 223                        DEBUGF("Am29LV800T\n");
 224                        info->flash_id += FLASH_AM800T;
 225                        info->sector_count = 19;
 226                        info->size = 0x00200000;
 227                        break;                  /* => 2 MB              */
 228
 229                case AMD_ID_LV800B:
 230                        DEBUGF("Am29LV400B\n");
 231                        info->flash_id += FLASH_AM800B;
 232                        info->sector_count = 19;
 233                        info->size = 0x00200000;
 234                        break;                  /* => 2 MB              */
 235
 236                case AMD_ID_LV160T:
 237                        DEBUGF("Am29LV160T\n");
 238                        info->flash_id += FLASH_AM160T;
 239                        info->sector_count = 35;
 240                        info->size = 0x00400000;
 241                        break;                  /* => 4 MB              */
 242
 243                case AMD_ID_LV160B:
 244                        DEBUGF("Am29LV160B\n");
 245                        info->flash_id += FLASH_AM160B;
 246                        info->sector_count = 35;
 247                        info->size = 0x00400000;
 248                        break;                  /* => 4 MB              */
 249
 250                case AMD_ID_LV320T:
 251                        DEBUGF("Am29LV320T\n");
 252                        info->flash_id += FLASH_AM320T;
 253                        info->sector_count = 67;
 254                        info->size = 0x00800000;
 255                        break;                  /* => 8 MB              */
 256
 257#if 0
 258                /* Has the same ID as AMD_ID_LV320T, to be fixed */
 259                case AMD_ID_LV320B:
 260                        DEBUGF("Am29LV320B\n");
 261                        info->flash_id += FLASH_AM320B;
 262                        info->sector_count = 67;
 263                        info->size = 0x00800000;
 264                        break;                  /* => 8 MB              */
 265#endif
 266
 267                case AMD_ID_LV033C:
 268                        DEBUGF("Am29LV033C\n");
 269                        info->flash_id += FLASH_AM033C;
 270                        info->sector_count = 64;
 271                        info->size = 0x01000000;
 272                        break;                  /* => 16Mb              */
 273
 274                case STM_ID_F040B:
 275                        DEBUGF("M29F040B\n");
 276                        info->flash_id += FLASH_AM040;
 277                        info->sector_count = 8;
 278                        info->size = 0x00080000;
 279                        break;                  /* => 512 kB            */
 280
 281                default:
 282                        info->flash_id = FLASH_UNKNOWN;
 283                        flash_reset (addr);
 284                        flash_to_mem();
 285                        return (0);             /* => no or unknown flash */
 286
 287        }
 288
 289        if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
 290                printf ("** ERROR: sector count %d > max (%d) **\n",
 291                        info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
 292                info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 293        }
 294
 295        if (! flash_get_offsets (addr, info)) {
 296                flash_reset (addr);
 297                flash_to_mem();
 298                return 0;
 299        }
 300
 301        /* check for protected sectors */
 302        for (i = 0; i < info->sector_count; i++) {
 303                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 304                /* D0 = 1 if protected */
 305                value = in8(info->start[i] + 2);
 306                iobarrier_rw();
 307                info->protect[i] = (value & 1) != 0;
 308        }
 309
 310        /*
 311         * Reset bank to read mode
 312         */
 313        flash_reset (addr);
 314
 315        flash_to_mem();
 316
 317        return (info->size);
 318}
 319
 320static int flash_get_offsets (ulong base, flash_info_t *info)
 321{
 322        unsigned int i;
 323
 324        switch (info->flash_id & FLASH_TYPEMASK) {
 325                case FLASH_AM040:
 326                        /* set sector offsets for uniform sector type   */
 327                        for (i = 0; i < info->sector_count; i++) {
 328                                info->start[i] = base + i * info->size /
 329                                                            info->sector_count;
 330                        }
 331                        break;
 332                default:
 333                        return 0;
 334        }
 335
 336        return 1;
 337}
 338
 339int flash_erase (flash_info_t *info, int s_first, int s_last)
 340{
 341        volatile ulong addr = info->start[0];
 342        int flag, prot, sect, l_sect;
 343        ulong start, now, last;
 344
 345        flash_to_xd();
 346
 347        if (s_first < 0 || s_first > s_last) {
 348                if (info->flash_id == FLASH_UNKNOWN) {
 349                        printf ("- missing\n");
 350                } else {
 351                        printf ("- no sectors to erase\n");
 352                }
 353                flash_to_mem();
 354                return 1;
 355        }
 356
 357        if (info->flash_id == FLASH_UNKNOWN) {
 358                printf ("Can't erase unknown flash type %08lx - aborted\n",
 359                        info->flash_id);
 360                flash_to_mem();
 361                return 1;
 362        }
 363
 364        prot = 0;
 365        for (sect=s_first; sect<=s_last; ++sect) {
 366                if (info->protect[sect]) {
 367                        prot++;
 368                }
 369        }
 370
 371        if (prot) {
 372                printf ("- Warning: %d protected sectors will not be erased!\n",
 373                        prot);
 374        } else {
 375                printf ("");
 376        }
 377
 378        l_sect = -1;
 379
 380        /* Disable interrupts which might cause a timeout here */
 381        flag = disable_interrupts();
 382
 383        out8(addr + 0x555, 0xAA);
 384        iobarrier_rw();
 385        out8(addr + 0x2AA, 0x55);
 386        iobarrier_rw();
 387        out8(addr + 0x555, 0x80);
 388        iobarrier_rw();
 389        out8(addr + 0x555, 0xAA);
 390        iobarrier_rw();
 391        out8(addr + 0x2AA, 0x55);
 392        iobarrier_rw();
 393
 394        /* Start erase on unprotected sectors */
 395        for (sect = s_first; sect<=s_last; sect++) {
 396                if (info->protect[sect] == 0) { /* not protected */
 397                        addr = info->start[sect];
 398                        out8(addr, 0x30);
 399                        iobarrier_rw();
 400                        l_sect = sect;
 401                }
 402        }
 403
 404        /* re-enable interrupts if necessary */
 405        if (flag)
 406                enable_interrupts();
 407
 408        /* wait at least 80us - let's wait 1 ms */
 409        udelay (1000);
 410
 411        /*
 412         * We wait for the last triggered sector
 413         */
 414        if (l_sect < 0)
 415                goto DONE;
 416
 417        start = get_timer (0);
 418        last  = start;
 419        addr = info->start[l_sect];
 420
 421        DEBUGF ("Start erase timeout: %d\n", CONFIG_SYS_FLASH_ERASE_TOUT);
 422
 423        while ((in8(addr) & 0x80) != 0x80) {
 424                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 425                        printf ("Timeout\n");
 426                        flash_reset (info->start[0]);
 427                        flash_to_mem();
 428                        return 1;
 429                }
 430                /* show that we're waiting */
 431                if ((now - last) > 1000) {      /* every second */
 432                        putc ('.');
 433                        last = now;
 434                }
 435                iobarrier_rw();
 436        }
 437
 438DONE:
 439        /* reset to read mode */
 440        flash_reset (info->start[0]);
 441        flash_to_mem();
 442
 443        printf (" done\n");
 444        return 0;
 445}
 446
 447/*
 448 * Copy memory to flash, returns:
 449 * 0 - OK
 450 * 1 - write timeout
 451 * 2 - Flash not erased
 452 */
 453int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 454{
 455        ulong cp, wp, data;
 456        int i, l, rc;
 457        ulong out_cnt = 0;
 458
 459        flash_to_xd();
 460
 461        wp = (addr & ~3);       /* get lower word aligned address */
 462
 463        /*
 464         * handle unaligned start bytes
 465         */
 466        if ((l = addr - wp) != 0) {
 467                data = 0;
 468                for (i=0, cp=wp; i<l; ++i, ++cp) {
 469                        data = (data << 8) | (*(uchar *)cp);
 470                }
 471                for (; i<4 && cnt>0; ++i) {
 472                        data = (data << 8) | *src++;
 473                        --cnt;
 474                        ++cp;
 475                }
 476                for (; cnt==0 && i<4; ++i, ++cp) {
 477                        data = (data << 8) | (*(uchar *)cp);
 478                }
 479
 480                if ((rc = write_word(info, wp, data)) != 0) {
 481                        flash_to_mem();
 482                        return (rc);
 483                }
 484                wp += 4;
 485        }
 486
 487        putc(219);
 488
 489        /*
 490         * handle word aligned part
 491         */
 492        while (cnt >= 4) {
 493            if (out_cnt>26214)
 494            {
 495                putc(219);
 496                out_cnt = 0;
 497            }
 498            data = 0;
 499            for (i=0; i<4; ++i) {
 500                data = (data << 8) | *src++;
 501            }
 502            if ((rc = write_word(info, wp, data)) != 0) {
 503                flash_to_mem();
 504                return (rc);
 505            }
 506            wp  += 4;
 507            cnt -= 4;
 508            out_cnt += 4;
 509        }
 510
 511        if (cnt == 0) {
 512                flash_to_mem();
 513                return (0);
 514        }
 515
 516        /*
 517         * handle unaligned tail bytes
 518         */
 519        data = 0;
 520        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 521                data = (data << 8) | *src++;
 522                --cnt;
 523        }
 524        for (; i<4; ++i, ++cp) {
 525                data = (data << 8) | (*(uchar *)cp);
 526        }
 527
 528        flash_to_mem();
 529        return (write_word(info, wp, data));
 530}
 531
 532/*
 533 * Write a word to Flash, returns:
 534 * 0 - OK
 535 * 1 - write timeout
 536 * 2 - Flash not erased
 537 */
 538static int write_word (flash_info_t *info, ulong dest, ulong data)
 539{
 540        volatile ulong addr = info->start[0];
 541        ulong start;
 542        int i;
 543
 544        flash_to_xd();
 545
 546        /* Check if Flash is (sufficiently) erased */
 547        if ((in32(dest) & data) != data) {
 548                flash_to_mem();
 549                return (2);
 550        }
 551
 552        /* write each byte out */
 553        for (i = 0; i < 4; i++) {
 554                char *data_ch = (char *)&data;
 555                int flag = disable_interrupts();
 556
 557                out8(addr + 0x555, 0xAA);
 558                iobarrier_rw();
 559                out8(addr + 0x2AA, 0x55);
 560                iobarrier_rw();
 561                out8(addr + 0x555, 0xA0);
 562                iobarrier_rw();
 563                out8(dest+i, data_ch[i]);
 564                iobarrier_rw();
 565
 566                /* re-enable interrupts if necessary */
 567                if (flag)
 568                        enable_interrupts();
 569
 570                /* data polling for D7 */
 571                start = get_timer (0);
 572                while ((in8(dest+i) & 0x80) != (data_ch[i] & 0x80)) {
 573                        if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 574                                flash_reset (addr);
 575                                flash_to_mem();
 576                                return (1);
 577                        }
 578                        iobarrier_rw();
 579                }
 580        }
 581
 582        flash_reset (addr);
 583        flash_to_mem();
 584        return (0);
 585}
 586
 587/*
 588 * Reset bank to read mode
 589 */
 590static void flash_reset (ulong addr)
 591{
 592        flash_to_xd();
 593        out8(addr, 0xF0);       /* reset bank */
 594        iobarrier_rw();
 595        flash_to_mem();
 596}
 597
 598void flash_print_info (flash_info_t *info)
 599{
 600        int i;
 601
 602        if (info->flash_id == FLASH_UNKNOWN) {
 603                printf ("missing or unknown FLASH type\n");
 604                return;
 605        }
 606
 607        switch (info->flash_id & FLASH_VENDMASK) {
 608        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 609        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
 610        case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
 611        case FLASH_MAN_STM:     printf ("SGS THOMSON ");        break;
 612        default:                printf ("Unknown Vendor ");     break;
 613        }
 614
 615        switch (info->flash_id & FLASH_TYPEMASK) {
 616        case FLASH_AM040:       printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n");
 617                                break;
 618        case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
 619                                break;
 620        case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
 621                                break;
 622        case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
 623                                break;
 624        case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
 625                                break;
 626        case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
 627                                break;
 628        case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
 629                                break;
 630        case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
 631                                break;
 632        case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
 633                                break;
 634        default:                printf ("Unknown Chip Type\n");
 635                                break;
 636        }
 637
 638        if (info->size % 0x100000 == 0) {
 639                printf ("  Size: %ld MB in %d Sectors\n",
 640                        info->size / 0x100000, info->sector_count);
 641        } else if (info->size % 0x400 == 0) {
 642                printf ("  Size: %ld KB in %d Sectors\n",
 643                        info->size / 0x400, info->sector_count);
 644        } else {
 645                printf ("  Size: %ld B in %d Sectors\n",
 646                        info->size, info->sector_count);
 647        }
 648
 649        printf ("  Sector Start Addresses:");
 650        for (i=0; i<info->sector_count; ++i) {
 651                if ((i % 5) == 0)
 652                        printf ("\n   ");
 653                printf (" %08lX%s",
 654                        info->start[i],
 655                        info->protect[i] ? " (RO)" : "     "
 656                );
 657        }
 658        printf ("\n");
 659}
 660