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