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