uboot/board/flagadm/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   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 <mpc8xx.h>
  26#include <flash.h>
  27
  28flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  29
  30/*-----------------------------------------------------------------------
  31 * Functions
  32 */
  33ulong flash_recognize (vu_long *base);
  34int write_word (flash_info_t *info, ulong dest, ulong data);
  35void flash_get_geometry (vu_long *base, flash_info_t *info);
  36void flash_unprotect(flash_info_t *info);
  37int _flash_real_protect(flash_info_t *info, long idx, int on);
  38
  39
  40unsigned long flash_init (void)
  41{
  42        volatile immap_t        *immap  = (immap_t *)CONFIG_SYS_IMMR;
  43        volatile memctl8xx_t    *memctl = &immap->im_memctl;
  44        int i;
  45        int rec;
  46
  47        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  48                flash_info[i].flash_id = FLASH_UNKNOWN;
  49        }
  50
  51        *((vu_short*)CONFIG_SYS_FLASH_BASE) = 0xffff;
  52
  53        flash_get_geometry ((vu_long*)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  54
  55        /* Remap FLASH according to real size */
  56        memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-flash_info[0].size & 0xFFFF8000);
  57        memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) |
  58                (memctl->memc_br0 & ~(BR_BA_MSK));
  59
  60        rec = flash_recognize((vu_long*)CONFIG_SYS_FLASH_BASE);
  61
  62        if (rec == FLASH_UNKNOWN) {
  63                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
  64                                flash_info[0].size, flash_info[0].size<<20);
  65        }
  66
  67#if CONFIG_SYS_FLASH_PROTECTION
  68        /*Unprotect all the flash memory*/
  69        flash_unprotect(&flash_info[0]);
  70#endif
  71
  72        *((vu_short*)CONFIG_SYS_FLASH_BASE) = 0xffff;
  73
  74        return (flash_info[0].size);
  75
  76#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  77        /* monitor protection ON by default */
  78        flash_protect(FLAG_PROTECT_SET,
  79                      CONFIG_SYS_MONITOR_BASE,
  80                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  81                      &flash_info[0]);
  82#endif
  83
  84#ifdef  CONFIG_ENV_IS_IN_FLASH
  85        /* ENV protection ON by default */
  86        flash_protect(FLAG_PROTECT_SET,
  87                      CONFIG_ENV_OFFSET,
  88                      CONFIG_ENV_OFFSET+CONFIG_ENV_SIZE-1,
  89                      &flash_info[0]);
  90#endif
  91        return (flash_info[0].size);
  92}
  93
  94
  95int flash_get_protect_status(flash_info_t * info, long idx)
  96{
  97        vu_short * base;
  98        ushort res;
  99
 100#ifdef DEBUG
 101        printf("\n Attempting to set protection info with %d sectors\n", info->sector_count);
 102#endif
 103
 104
 105        base = (vu_short*)info->start[idx];
 106
 107        *(base) = 0xffff;
 108
 109        *(base + 0x55) = 0x0098;
 110        res = base[0x2];
 111
 112        *(base) = 0xffff;
 113
 114        if(res != 0)
 115                res = 1;
 116        else
 117                res = 0;
 118
 119        return res;
 120}
 121
 122void flash_get_geometry (vu_long *base, flash_info_t *info)
 123{
 124        int i,j;
 125        ulong ner = 0;
 126        vu_short * sb  = (vu_short*)base;
 127        ulong offset = (ulong)base;
 128
 129        /* Read Device geometry */
 130
 131        *sb = 0xffff;
 132
 133        *sb = 0x0090;
 134
 135        info->flash_id = ((ulong)base[0x0]);
 136#ifdef DEBUG
 137        printf("Id is %x\n", (uint)(ulong)info->flash_id);
 138#endif
 139
 140        *sb = 0xffff;
 141
 142        *(sb+0x55) = 0x0098;
 143
 144        info->size = 1 << (sb[0x27]); /* Read flash size */
 145
 146#ifdef DEBUG
 147        printf("Size is %x\n", (uint)(ulong)info->size);
 148#endif
 149
 150        *sb = 0xffff;
 151
 152        *(sb + 0x55) = 0x0098;
 153        ner = sb[0x2c] ; /*Number of erase regions*/
 154
 155#ifdef DEBUG
 156        printf("Number of erase regions %x\n", (uint)ner);
 157#endif
 158
 159        info->sector_count = 0;
 160
 161        for(i = 0; i < ner; i++)
 162        {
 163                uint s;
 164                uint count;
 165                uint t1,t2,t3,t4;
 166
 167                *sb = 0xffff;
 168
 169                *(sb + 0x55) = 0x0098;
 170
 171                t1 = sb[0x2d + i*4];
 172                t2 = sb[0x2e + i*4];
 173                t3 = sb[0x2f + i*4];
 174                t4 = sb[0x30 + i*4];
 175
 176                count = ((t1 & 0x00ff) | (((t2 & 0x00ff) << 8) & 0xff00) )+ 1; /*sector count*/
 177                s = ((t3 & 0x00ff) | (((t4 & 0x00ff) << 8) & 0xff00)) * 256;; /*Sector size*/
 178
 179#ifdef DEBUG
 180                printf("count and size %x, %x\n", count, s);
 181                printf("sector count for erase region %d is %d\n", i, count);
 182#endif
 183                for(j = 0; j < count; j++)
 184                {
 185#ifdef DEBUG
 186                        printf("%x, ", (uint)offset);
 187#endif
 188                        info->start[ info->sector_count + j] = offset;
 189                        offset += s;
 190                }
 191                info->sector_count += count;
 192        }
 193
 194        if ((offset - (ulong)base) != info->size)
 195                printf("WARNING reported size %x does not match to calculted size %x.\n"
 196                                , (uint)info->size, (uint)(offset - (ulong)base) );
 197
 198        /* Next check if there are any sectors protected.*/
 199
 200        for(i = 0; i < info->sector_count; i++)
 201                info->protect[i] = flash_get_protect_status(info, i);
 202
 203        *sb = 0xffff;
 204}
 205
 206/*-----------------------------------------------------------------------
 207 */
 208void flash_print_info  (flash_info_t *info)
 209{
 210        int i;
 211
 212        if (info->flash_id == FLASH_UNKNOWN) {
 213                printf ("missing or unknown FLASH type\n");
 214                return ;
 215        }
 216
 217        switch (info->flash_id & FLASH_VENDMASK) {
 218        case INTEL_MANUFACT & FLASH_VENDMASK:
 219                printf ("Intel ");
 220                break;
 221        default:
 222                printf ("Unknown Vendor ");
 223                break;
 224        }
 225
 226        switch (info->flash_id & FLASH_TYPEMASK) {
 227        case INTEL_ID_28F320C3B & FLASH_TYPEMASK:
 228                printf ("28F320RC3(4 MB)\n");
 229                break;
 230        case INTEL_ID_28F320J3A:
 231                printf("28F320J3A (4 MB)\n");
 232                break;
 233        default:
 234                printf ("Unknown Chip Type\n");
 235                        break;
 236        }
 237
 238        printf ("  Size: %ld MB in %d Sectors\n",
 239                info->size >> 20, info->sector_count);
 240
 241        printf ("  Sector Start Addresses:");
 242        for (i=0; i<info->sector_count; ++i) {
 243                if ((i % 4) == 0)
 244                        printf ("\n   ");
 245                printf ("  %02d %08lX%s",
 246                        i, info->start[i],
 247                        info->protect[i]!=0 ? " (RO)" : "     "
 248                );
 249        }
 250        printf ("\n");
 251        return ;
 252}
 253
 254ulong flash_recognize (vu_long *base)
 255{
 256        ulong id;
 257        ulong res = FLASH_UNKNOWN;
 258        vu_short * sb = (vu_short*)base;
 259
 260        *sb = 0xffff;
 261
 262        *sb = 0x0090;
 263        id = base[0];
 264
 265        switch (id & 0x00FF0000)
 266        {
 267                case (MT_MANUFACT & 0x00FF0000):        /* MT or => Intel */
 268                case (INTEL_ALT_MANU & 0x00FF0000):
 269                res = FLASH_MAN_INTEL;
 270                break;
 271        default:
 272                res = FLASH_UNKNOWN;
 273        }
 274
 275        *sb = 0xffff;
 276
 277        return res;
 278}
 279
 280/*-----------------------------------------------------------------------*/
 281#define INTEL_FLASH_STATUS_BLS  0x02
 282#define INTEL_FLASH_STATUS_PSS  0x04
 283#define INTEL_FLASH_STATUS_VPPS 0x08
 284#define INTEL_FLASH_STATUS_PS   0x10
 285#define INTEL_FLASH_STATUS_ES   0x20
 286#define INTEL_FLASH_STATUS_ESS  0x40
 287#define INTEL_FLASH_STATUS_WSMS 0x80
 288
 289int     flash_decode_status_bits(char status)
 290{
 291        int err = 0;
 292
 293        if(!(status & INTEL_FLASH_STATUS_WSMS)) {
 294                printf("Busy\n");
 295                err = -1;
 296        }
 297
 298        if(status & INTEL_FLASH_STATUS_ESS) {
 299                printf("Erase suspended\n");
 300                err = -1;
 301        }
 302
 303        if(status & INTEL_FLASH_STATUS_ES) {
 304                printf("Error in block erase\n");
 305                err = -1;
 306        }
 307
 308        if(status & INTEL_FLASH_STATUS_PS) {
 309                printf("Error in programming\n");
 310                err = -1;
 311        }
 312
 313        if(status & INTEL_FLASH_STATUS_VPPS) {
 314                printf("Vpp low, operation aborted\n");
 315                err = -1;
 316        }
 317
 318        if(status & INTEL_FLASH_STATUS_PSS) {
 319                printf("Program is suspended\n");
 320                err = -1;
 321        }
 322
 323        if(status & INTEL_FLASH_STATUS_BLS) {
 324                printf("Attempting to program/erase a locked sector\n");
 325                err = -1;
 326        }
 327
 328        if((status & INTEL_FLASH_STATUS_PS) &&
 329           (status & INTEL_FLASH_STATUS_ES) &&
 330           (status & INTEL_FLASH_STATUS_ESS)) {
 331                printf("A command sequence error\n");
 332                return -1;
 333        }
 334
 335        return err;
 336}
 337
 338/*-----------------------------------------------------------------------
 339 */
 340
 341int     flash_erase (flash_info_t *info, int s_first, int s_last)
 342{
 343        vu_short *addr;
 344        int flag, prot, sect;
 345        ulong start, now;
 346        int rcode = 0;
 347
 348        if ((s_first < 0) || (s_first > s_last)) {
 349                if (info->flash_id == FLASH_UNKNOWN) {
 350                        printf ("- missing\n");
 351                } else {
 352                        printf ("- no sectors to erase\n");
 353                }
 354                return 1;
 355        }
 356
 357        if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK)) {
 358                printf ("Can't erase unknown flash type %08lx - aborted\n",
 359                        info->flash_id);
 360                return 1;
 361        }
 362
 363        prot = 0;
 364        for (sect=s_first; sect<=s_last; ++sect) {
 365                if (info->protect[sect]) {
 366                        prot++;
 367                }
 368        }
 369
 370        if (prot) {
 371                printf ("- Warning: %d protected sectors will not be erased!\n",
 372                        prot);
 373        } else {
 374                printf ("\n");
 375        }
 376
 377        start = get_timer (0);
 378
 379        /* Start erase on unprotected sectors */
 380        for (sect = s_first; sect<=s_last; sect++) {
 381                char tmp;
 382
 383                if (info->protect[sect] == 0) { /* not protected */
 384                        addr = (vu_short *)(info->start[sect]);
 385
 386                        /* Disable interrupts which might cause a timeout here */
 387                        flag = disable_interrupts();
 388
 389                        /* Single Block Erase Command */
 390                        *addr = 0x0020;
 391                        /* Confirm */
 392                        *addr = 0x00D0;
 393                        /* Resume Command, as per errata update */
 394                        *addr = 0x00D0;
 395
 396                        /* re-enable interrupts if necessary */
 397                        if (flag)
 398                                enable_interrupts();
 399
 400                        *addr = 0x70; /*Read status register command*/
 401                        tmp = (short)*addr & 0x00FF; /* Read the status */
 402                        while (!(tmp & INTEL_FLASH_STATUS_WSMS)) {
 403                                if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 404                                        *addr = 0x0050; /* Reset the status register */
 405                                        *addr = 0xffff;
 406                                        printf ("Timeout\n");
 407                                        return 1;
 408                                }
 409                                /* show that we're waiting */
 410                                if ((now - start) > 1000) {     /* every second */
 411                                        putc ('.');
 412                                }
 413                                udelay(100000); /* 100 ms */
 414                                *addr = 0x0070; /*Read status register command*/
 415                                tmp = (short)*addr & 0x00FF; /* Read status */
 416                                start = get_timer(0);
 417                        }
 418                        if( tmp & INTEL_FLASH_STATUS_ES )
 419                                flash_decode_status_bits(tmp);
 420
 421                        *addr = 0x0050; /* Reset the status register */
 422                        *addr = 0xffff; /* Reset to read mode */
 423                }
 424        }
 425
 426
 427        printf (" done\n");
 428        return rcode;
 429}
 430
 431void flash_unprotect (flash_info_t *info)
 432{
 433        /*We can only unprotect the whole flash at once*/
 434        /*Therefore we must prevent the _flash_real_protect()*/
 435        /*from re-protecting sectors, that ware protected before */
 436        /*we called flash_real_protect();*/
 437
 438        int i;
 439
 440        for(i = 0; i < info->sector_count; i++)
 441                info->protect[i] = 0;
 442
 443#ifdef CONFIG_SYS_FLASH_PROTECTION
 444                _flash_real_protect(info, 0, 0);
 445#endif
 446}
 447
 448/*-----------------------------------------------------------------------
 449 * Copy memory to flash, returns:
 450 * 0 - OK
 451 * 1 - write timeout
 452 * 2 - Flash not erased
 453 */
 454
 455int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 456{
 457        ulong cp, wp, data;
 458        int i, l, rc;
 459
 460        wp = (addr & ~3);       /* get lower word aligned address */
 461
 462        /*
 463         * handle unaligned start bytes
 464         */
 465        if ((l = addr - wp) != 0) {
 466                data = 0;
 467                for (i=0, cp=wp; i<l; ++i, ++cp) {
 468                        data = (data << 8) | (*(uchar *)cp);
 469                }
 470                for (; i<4 && cnt>0; ++i) {
 471                        data = (data << 8) | *src++;
 472                        --cnt;
 473                        ++cp;
 474                }
 475                for (; cnt==0 && i<4; ++i, ++cp) {
 476                        data = (data << 8) | (*(uchar *)cp);
 477                }
 478
 479                if ((rc = write_word(info, wp, data)) != 0) {
 480                        return (rc);
 481                }
 482                wp += 4;
 483        }
 484
 485        /*
 486         * handle word aligned part
 487         */
 488        while (cnt >= 4) {
 489                data = 0;
 490                for (i=0; i<4; ++i) {
 491                        data = (data << 8) | *src++;
 492                }
 493                if ((rc = write_word(info, wp, data)) != 0) {
 494                        return (rc);
 495                }
 496                wp  += 4;
 497                cnt -= 4;
 498        }
 499
 500        if (cnt == 0) {
 501                return (0);
 502        }
 503
 504        /*
 505         * handle unaligned tail bytes
 506         */
 507        data = 0;
 508        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 509                data = (data << 8) | *src++;
 510                --cnt;
 511        }
 512        for (; i<4; ++i, ++cp) {
 513                data = (data << 8) | (*(uchar *)cp);
 514        }
 515
 516        return (write_word(info, wp, data));
 517}
 518
 519/*-----------------------------------------------------------------------
 520 * Write a word to Flash, returns:
 521 * 0 - OK
 522 * 1 - write timeout
 523 * 2 - Flash not erased
 524 */
 525int write_word (flash_info_t *info, ulong dest, ulong da)
 526{
 527        vu_short *addr = (vu_short *)dest;
 528        ulong start;
 529        char csr;
 530        int flag;
 531        int i;
 532        union {
 533                u32 data32;
 534                u16 data16[2];
 535        } data;
 536
 537        data.data32 = da;
 538
 539        /* Check if Flash is (sufficiently) erased */
 540        if (((*addr & data.data16[0]) != data.data16[0]) ||
 541            ((*(addr+1) & data.data16[1]) != data.data16[1])) {
 542                return (2);
 543        }
 544        /* Disable interrupts which might cause a timeout here */
 545        flag = disable_interrupts();
 546
 547        for(i = 0; i < 2; i++)
 548        {
 549                /* Write Command */
 550                *addr = 0x0010;
 551
 552                /* Write Data */
 553                *addr = data.data16[i];
 554
 555                /* re-enable interrupts if necessary */
 556                if (flag)
 557                        enable_interrupts();
 558
 559                /* data polling for D7 */
 560                start = get_timer (0);
 561                flag  = 0;
 562                *addr = 0x0070; /*Read statusregister command */
 563                while (((csr = *addr) & INTEL_FLASH_STATUS_WSMS)!=INTEL_FLASH_STATUS_WSMS) {
 564                        if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 565                                flag = 1;
 566                                break;
 567                        }
 568                        *addr = 0x0070; /*Read statusregister command */
 569                }
 570                if (csr & INTEL_FLASH_STATUS_PSS) {
 571                        printf ("CSR indicates write error (%0x) at %08lx\n",
 572                                        csr, (ulong)addr);
 573                        flag = 1;
 574                }
 575
 576                /* Clear Status Registers Command */
 577                *addr = 0x0050;
 578                /* Reset to read array mode */
 579                *addr = 0xffff;
 580                addr++;
 581        }
 582
 583        return (flag);
 584}
 585
 586int flash_real_protect(flash_info_t *info, long offset, int prot)
 587{
 588        int i, idx;
 589
 590        for(idx = 0; idx < info->sector_count; idx++)
 591                if(info->start[idx] == offset)
 592                        break;
 593
 594        if(idx==info->sector_count)
 595                return -1;
 596
 597        if(prot == 0) {
 598                /* Unprotect one sector, which means unprotect all flash
 599                 * and reprotect the other protected sectors.
 600                 */
 601                _flash_real_protect(info, 0, 0); /* Unprotects the whole flash*/
 602                info->protect[idx] = 0;
 603
 604                for(i = 0; i < info->sector_count; i++)
 605                        if(info->protect[i])
 606                                _flash_real_protect(info, i, 1);
 607                }
 608        else {
 609                /* We can protect individual sectors */
 610                _flash_real_protect(info, idx, 1);
 611        }
 612
 613        for( i = 0; i < info->sector_count; i++)
 614                info->protect[i] = flash_get_protect_status(info, i);
 615
 616        return 0;
 617}
 618
 619int _flash_real_protect(flash_info_t *info, long idx, int prot)
 620{
 621        vu_short *addr;
 622        int flag;
 623        ushort cmd;
 624        ushort tmp;
 625        ulong now, start;
 626
 627        if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK)) {
 628                printf ("Can't change protection for unknown flash type %08lx - aborted\n",
 629                        info->flash_id);
 630                return -1;
 631        }
 632
 633        if(prot == 0) {
 634                /*Unlock the sector*/
 635                cmd = 0x00D0;
 636        }
 637        else {
 638                /*Lock the sector*/
 639                cmd = 0x0001;
 640        }
 641
 642        addr = (vu_short *)(info->start[idx]);
 643
 644        /* If chip is busy, wait for it */
 645        start = get_timer(0);
 646        *addr = 0x0070; /*Read status register command*/
 647        tmp = ((ushort)(*addr))&0x00ff; /*Read the status*/
 648        while(!(tmp & INTEL_FLASH_STATUS_WSMS)) {
 649                /*Write State Machine Busy*/
 650                /*Wait untill done or timeout.*/
 651                if ((now=get_timer(start)) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 652                        *addr = 0x0050; /* Reset the status register */
 653                        *addr = 0xffff; /* Reset the chip */
 654                        printf ("TTimeout\n");
 655                        return 1;
 656                }
 657                *addr = 0x0070;
 658                tmp = ((ushort)(*addr))&0x00ff; /*Read the status*/
 659                start = get_timer(0);
 660        }
 661
 662        /* Disable interrupts which might cause a timeout here */
 663        flag = disable_interrupts();
 664
 665        /* Unlock block*/
 666        *addr = 0x0060;
 667
 668        *addr = cmd;
 669
 670        /* re-enable interrupts if necessary */
 671        if (flag)
 672                enable_interrupts();
 673
 674        start = get_timer(0);
 675        *addr = 0x0070; /*Read status register command*/
 676        tmp = ((ushort)(*addr)) & 0x00FF; /* Read the status */
 677        while (!(tmp & INTEL_FLASH_STATUS_WSMS)) {
 678                /* Write State Machine Busy */
 679                if ((now=get_timer(start)) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 680                        *addr = 0x0050; /* Reset the status register */
 681                        *addr = 0xffff;
 682                        printf ("Timeout\n");
 683                        return 1;
 684                }
 685                /* show that we're waiting */
 686                if ((now - start) > 1000) {     /* every second */
 687                        putc ('.');
 688                }
 689                udelay(100000); /* 100 ms */
 690                *addr = 0x70; /*Read status register command*/
 691                tmp = (short)*addr & 0x00FF; /* Read status */
 692                start = get_timer(0);
 693        }
 694        if( tmp & INTEL_FLASH_STATUS_PS )
 695                flash_decode_status_bits(tmp);
 696
 697        *addr =0x0050; /*Clear status register*/
 698
 699        /* reset to read mode */
 700        *addr = 0xffff;
 701
 702        return 0;
 703}
 704