uboot/board/cpu87/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001-2005
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * Flash Routines for Intel devices
   6 *
   7 *--------------------------------------------------------------------
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <mpc8xx.h>
  13#include "cpu87.h"
  14
  15flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  16
  17/*-----------------------------------------------------------------------
  18 */
  19ulong flash_int_get_size (volatile unsigned long *baseaddr,
  20                                          flash_info_t * info)
  21{
  22        short i;
  23        unsigned long flashtest_h, flashtest_l;
  24
  25        info->sector_count = info->size = 0;
  26        info->flash_id = FLASH_UNKNOWN;
  27
  28        /* Write identify command sequence and test FLASH answer
  29         */
  30        baseaddr[0] = 0x00900090;
  31        baseaddr[1] = 0x00900090;
  32
  33        flashtest_h = baseaddr[0];      /* manufacturer ID      */
  34        flashtest_l = baseaddr[1];
  35
  36        if (flashtest_h != INTEL_MANUFACT || flashtest_l != INTEL_MANUFACT)
  37                return (0);             /* no or unknown flash  */
  38
  39        flashtest_h = baseaddr[2];      /* device ID            */
  40        flashtest_l = baseaddr[3];
  41
  42        if (flashtest_h != flashtest_l)
  43                return (0);
  44
  45        switch (flashtest_h) {
  46        case INTEL_ID_28F160C3B:
  47                info->flash_id = FLASH_28F160C3B;
  48                info->sector_count = 39;
  49                info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
  50                break;
  51        case INTEL_ID_28F160F3B:
  52                info->flash_id = FLASH_28F160F3B;
  53                info->sector_count = 39;
  54                info->size = 0x00800000;        /* 4 * 2 MB = 8 MB      */
  55                break;
  56        case INTEL_ID_28F640C3B:
  57                info->flash_id = FLASH_28F640C3B;
  58                info->sector_count = 135;
  59                info->size = 0x02000000;        /* 16 * 2 MB = 32 MB    */
  60                break;
  61        default:
  62                return (0);                     /* no or unknown flash  */
  63        }
  64
  65        info->flash_id |= INTEL_MANUFACT << 16; /* set manufacturer offset */
  66
  67        if (info->flash_id & FLASH_BTYPE) {
  68                volatile unsigned long *tmp = baseaddr;
  69
  70                /* set up sector start adress table (bottom sector type)
  71                 * AND unlock the sectors (if our chip is 160C3)
  72                 */
  73                for (i = 0; i < info->sector_count; i++) {
  74                        if (((info->flash_id & FLASH_TYPEMASK) == FLASH_28F160C3B) ||
  75                            ((info->flash_id & FLASH_TYPEMASK) == FLASH_28F640C3B)) {
  76                                tmp[0] = 0x00600060;
  77                                tmp[1] = 0x00600060;
  78                                tmp[0] = 0x00D000D0;
  79                                tmp[1] = 0x00D000D0;
  80                        }
  81                        info->start[i] = (uint) tmp;
  82                        tmp += i < 8 ? 0x2000 : 0x10000; /* pointer arith       */
  83                }
  84        }
  85
  86        memset (info->protect, 0, info->sector_count);
  87
  88        baseaddr[0] = 0x00FF00FF;
  89        baseaddr[1] = 0x00FF00FF;
  90
  91        return (info->size);
  92}
  93
  94static ulong flash_amd_get_size (vu_char *addr, flash_info_t *info)
  95{
  96        short i;
  97        uchar vendor, devid;
  98        ulong base = (ulong)addr;
  99
 100        /* Write auto select command: read Manufacturer ID */
 101        addr[0x0555] = 0xAA;
 102        addr[0x02AA] = 0x55;
 103        addr[0x0555] = 0x90;
 104
 105        udelay(1000);
 106
 107        vendor = addr[0];
 108        devid = addr[1] & 0xff;
 109
 110        /* only support AMD */
 111        if (vendor != 0x01) {
 112                return 0;
 113        }
 114
 115        vendor &= 0xf;
 116        devid &= 0xff;
 117
 118        if (devid == AMD_ID_F040B) {
 119                info->flash_id     = vendor << 16 | devid;
 120                info->sector_count = 8;
 121                info->size         = info->sector_count * 0x10000;
 122        }
 123        else if (devid == AMD_ID_F080B) {
 124                info->flash_id     = vendor << 16 | devid;
 125                info->sector_count = 16;
 126                info->size         = 4 * info->sector_count * 0x10000;
 127        }
 128        else if (devid == AMD_ID_F016D) {
 129                info->flash_id     = vendor << 16 | devid;
 130                info->sector_count = 32;
 131                info->size         = 4 * info->sector_count * 0x10000;
 132        }
 133        else {
 134                printf ("## Unknown Flash Type: %02x\n", devid);
 135                return 0;
 136        }
 137
 138        /* check for protected sectors */
 139        for (i = 0; i < info->sector_count; i++) {
 140                /* sector base address */
 141                info->start[i] = base + i * (info->size / info->sector_count);
 142                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 143                /* D0 = 1 if protected */
 144                addr = (volatile unsigned char *)(info->start[i]);
 145                info->protect[i] = addr[2] & 1;
 146        }
 147
 148        /*
 149         * Prevent writes to uninitialized FLASH.
 150         */
 151        if (info->flash_id != FLASH_UNKNOWN) {
 152                addr = (vu_char *)info->start[0];
 153                addr[0] = 0xF0; /* reset bank */
 154        }
 155
 156        return (info->size);
 157}
 158
 159
 160/*-----------------------------------------------------------------------
 161 */
 162unsigned long flash_init (void)
 163{
 164        unsigned long size_b0 = 0;
 165        unsigned long size_b1 = 0;
 166        int i;
 167
 168        /* Init: no FLASHes known
 169         */
 170        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
 171                flash_info[i].flash_id = FLASH_UNKNOWN;
 172        }
 173
 174        /* Disable flash protection */
 175        CPU86_BCR |= (CPU86_BCR_FWPT | CPU86_BCR_FWRE);
 176
 177        /* Static FLASH Bank configuration here (only one bank) */
 178
 179        size_b0 = flash_int_get_size ((ulong *) CONFIG_SYS_FLASH_BASE, &flash_info[0]);
 180        size_b1 = flash_amd_get_size ((uchar *) CONFIG_SYS_BOOTROM_BASE, &flash_info[1]);
 181
 182        if (size_b0 > 0 || size_b1 > 0) {
 183
 184                printf("(");
 185
 186                if (size_b0 > 0) {
 187                        puts ("Bank#1 - ");
 188                        print_size (size_b0, (size_b1 > 0) ? ", " : ") ");
 189                }
 190
 191                if (size_b1 > 0) {
 192                        puts ("Bank#2 - ");
 193                        print_size (size_b1, ") ");
 194                }
 195        }
 196        else {
 197                printf ("## No FLASH found.\n");
 198                return 0;
 199        }
 200        /* protect monitor and environment sectors
 201         */
 202
 203#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_BOOTROM_BASE
 204        if (size_b1) {
 205                /* If U-Boot is booted from ROM the CONFIG_SYS_MONITOR_BASE > CONFIG_SYS_FLASH_BASE
 206                 * but we shouldn't protect it.
 207                 */
 208
 209                flash_protect  (FLAG_PROTECT_SET,
 210                                CONFIG_SYS_MONITOR_BASE,
 211                                CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[1]
 212                );
 213        }
 214#else
 215#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
 216        flash_protect (FLAG_PROTECT_SET,
 217                       CONFIG_SYS_MONITOR_BASE,
 218                       CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]
 219        );
 220#endif
 221#endif
 222
 223#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
 224# ifndef  CONFIG_ENV_SIZE
 225#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
 226# endif
 227# if CONFIG_ENV_ADDR >= CONFIG_SYS_BOOTROM_BASE
 228        if (size_b1) {
 229                flash_protect (FLAG_PROTECT_SET,
 230                                CONFIG_ENV_ADDR,
 231                                CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[1]);
 232        }
 233# else
 234        flash_protect (FLAG_PROTECT_SET,
 235                       CONFIG_ENV_ADDR,
 236                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
 237# endif
 238#endif
 239
 240        return (size_b0 + size_b1);
 241}
 242
 243/*-----------------------------------------------------------------------
 244 */
 245void flash_print_info (flash_info_t * info)
 246{
 247        int i;
 248
 249        if (info->flash_id == FLASH_UNKNOWN) {
 250                printf ("missing or unknown FLASH type\n");
 251                return;
 252        }
 253
 254        switch ((info->flash_id >> 16) & 0xff) {
 255        case 0x89:
 256                printf ("INTEL ");
 257                break;
 258        case 0x1:
 259                printf ("AMD ");
 260                break;
 261        default:
 262                printf ("Unknown Vendor ");
 263                break;
 264        }
 265
 266        switch (info->flash_id & FLASH_TYPEMASK) {
 267        case FLASH_28F160C3B:
 268                printf ("28F160C3B (16 Mbit, bottom sector)\n");
 269                break;
 270        case FLASH_28F160F3B:
 271                printf ("28F160F3B (16 Mbit, bottom sector)\n");
 272                break;
 273        case FLASH_28F640C3B:
 274                printf ("28F640C3B (64 M, bottom sector)\n");
 275                break;
 276        case AMD_ID_F040B:
 277                printf ("AM29F040B (4 Mbit)\n");
 278                break;
 279        default:
 280                printf ("Unknown Chip Type\n");
 281                break;
 282        }
 283
 284        if (info->size < 0x100000)
 285                printf ("  Size: %ld KB in %d Sectors\n",
 286                                info->size >> 10, info->sector_count);
 287        else
 288                printf ("  Size: %ld MB in %d Sectors\n",
 289                                info->size >> 20, info->sector_count);
 290
 291        printf ("  Sector Start Addresses:");
 292        for (i = 0; i < info->sector_count; ++i) {
 293                if ((i % 5) == 0)
 294                        printf ("\n   ");
 295                printf (" %08lX%s",
 296                        info->start[i],
 297                        info->protect[i] ? " (RO)" : "     "
 298                );
 299        }
 300        printf ("\n");
 301}
 302
 303/*-----------------------------------------------------------------------
 304 */
 305int flash_erase (flash_info_t * info, int s_first, int s_last)
 306{
 307        vu_char *addr = (vu_char *)(info->start[0]);
 308        int flag, prot, sect, l_sect;
 309        ulong start, now, last;
 310
 311        if ((s_first < 0) || (s_first > s_last)) {
 312                if (info->flash_id == FLASH_UNKNOWN) {
 313                        printf ("- missing\n");
 314                } else {
 315                        printf ("- no sectors to erase\n");
 316                }
 317                return 1;
 318        }
 319
 320        prot = 0;
 321        for (sect = s_first; sect <= s_last; sect++) {
 322                if (info->protect[sect])
 323                        prot++;
 324        }
 325
 326        if (prot) {
 327                printf ("- Warning: %d protected sectors will not be erased!\n",
 328                                prot);
 329        } else {
 330                printf ("\n");
 331        }
 332
 333        /* Check the type of erased flash
 334         */
 335        if (info->flash_id >> 16 == 0x1) {
 336                /* Erase AMD flash
 337                 */
 338                l_sect = -1;
 339
 340                /* Disable interrupts which might cause a timeout here */
 341                flag = disable_interrupts();
 342
 343                addr[0x0555] = 0xAA;
 344                addr[0x02AA] = 0x55;
 345                addr[0x0555] = 0x80;
 346                addr[0x0555] = 0xAA;
 347                addr[0x02AA] = 0x55;
 348
 349                /* wait at least 80us - let's wait 1 ms */
 350                udelay (1000);
 351
 352                /* Start erase on unprotected sectors */
 353                for (sect = s_first; sect<=s_last; sect++) {
 354                        if (info->protect[sect] == 0) { /* not protected */
 355                                addr = (vu_char *)(info->start[sect]);
 356                                addr[0] = 0x30;
 357                                l_sect = sect;
 358                        }
 359                }
 360
 361                /* re-enable interrupts if necessary */
 362                if (flag)
 363                        enable_interrupts();
 364
 365                /* wait at least 80us - let's wait 1 ms */
 366                udelay (1000);
 367
 368                /*
 369                 * We wait for the last triggered sector
 370                 */
 371                if (l_sect < 0)
 372                        goto AMD_DONE;
 373
 374                start = get_timer (0);
 375                last  = start;
 376                addr = (vu_char *)(info->start[l_sect]);
 377                while ((addr[0] & 0x80) != 0x80) {
 378                        if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 379                                printf ("Timeout\n");
 380                                return 1;
 381                        }
 382                        /* show that we're waiting */
 383                        if ((now - last) > 1000) {      /* every second */
 384                                serial_putc ('.');
 385                                last = now;
 386                        }
 387                }
 388
 389AMD_DONE:
 390                /* reset to read mode */
 391                addr = (volatile unsigned char *)info->start[0];
 392                addr[0] = 0xF0;     /* reset bank */
 393
 394        } else {
 395                /* Erase Intel flash
 396                 */
 397
 398                /* Start erase on unprotected sectors
 399                 */
 400                for (sect = s_first; sect <= s_last; sect++) {
 401                        volatile ulong *addr =
 402                                (volatile unsigned long *) info->start[sect];
 403
 404                        start = get_timer (0);
 405                        last = start;
 406                        if (info->protect[sect] == 0) {
 407                        /* Disable interrupts which might cause a timeout here
 408                         */
 409                                flag = disable_interrupts ();
 410
 411                                /* Erase the block
 412                                 */
 413                                addr[0] = 0x00200020;
 414                                addr[1] = 0x00200020;
 415                                addr[0] = 0x00D000D0;
 416                                addr[1] = 0x00D000D0;
 417
 418                                /* re-enable interrupts if necessary
 419                                 */
 420                                if (flag)
 421                                        enable_interrupts ();
 422
 423                                /* wait at least 80us - let's wait 1 ms
 424                                 */
 425                                udelay (1000);
 426
 427                                last = start;
 428                                while ((addr[0] & 0x00800080) != 0x00800080 ||
 429                                   (addr[1] & 0x00800080) != 0x00800080) {
 430                                        if ((now = get_timer (start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 431                                                printf ("Timeout (erase suspended!)\n");
 432                                                /* Suspend erase
 433                                                 */
 434                                                addr[0] = 0x00B000B0;
 435                                                addr[1] = 0x00B000B0;
 436                                                goto DONE;
 437                                        }
 438                                        /* show that we're waiting
 439                                         */
 440                                        if ((now - last) > 1000) {      /* every second */
 441                                                serial_putc ('.');
 442                                                last = now;
 443                                        }
 444                                }
 445                                if (addr[0] & 0x00220022 || addr[1] & 0x00220022) {
 446                                        printf ("*** ERROR: erase failed!\n");
 447                                        goto DONE;
 448                                }
 449                        }
 450                        /* Clear status register and reset to read mode
 451                         */
 452                        addr[0] = 0x00500050;
 453                        addr[1] = 0x00500050;
 454                        addr[0] = 0x00FF00FF;
 455                        addr[1] = 0x00FF00FF;
 456                }
 457        }
 458
 459        printf (" done\n");
 460
 461DONE:
 462        return 0;
 463}
 464
 465static int write_word (flash_info_t *, volatile unsigned long *, ulong);
 466static int write_byte (flash_info_t *info, ulong dest, uchar data);
 467
 468/*-----------------------------------------------------------------------
 469 * Copy memory to flash, returns:
 470 * 0 - OK
 471 * 1 - write timeout
 472 * 2 - Flash not erased
 473 */
 474int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 475{
 476        ulong v;
 477        int i, l, rc, cc = cnt, res = 0;
 478
 479        if (info->flash_id >> 16 == 0x1) {
 480
 481                /* Write to AMD 8-bit flash
 482                 */
 483                while (cnt > 0) {
 484                        if ((rc = write_byte(info, addr, *src)) != 0) {
 485                                return (rc);
 486                        }
 487                        addr++;
 488                        src++;
 489                        cnt--;
 490                }
 491
 492                return (0);
 493        } else {
 494
 495                /* Write to Intel 64-bit flash
 496                 */
 497                for (v=0; cc > 0; addr += 4, cc -= 4 - l) {
 498                        l = (addr & 3);
 499                        addr &= ~3;
 500
 501                        for (i = 0; i < 4; i++) {
 502                                v = (v << 8) + (i < l || i - l >= cc ?
 503                                        *((unsigned char *) addr + i) : *src++);
 504                        }
 505
 506                        if ((res = write_word (info, (volatile unsigned long *) addr, v)) != 0)
 507                                break;
 508                }
 509        }
 510
 511        return (res);
 512}
 513
 514/*-----------------------------------------------------------------------
 515 * Write a word to Flash, returns:
 516 * 0 - OK
 517 * 1 - write timeout
 518 * 2 - Flash not erased
 519 */
 520static int write_word (flash_info_t * info, volatile unsigned long *addr,
 521                                           ulong data)
 522{
 523        int flag, res = 0;
 524        ulong start;
 525
 526        /* Check if Flash is (sufficiently) erased
 527         */
 528        if ((*addr & data) != data)
 529                return (2);
 530
 531        /* Disable interrupts which might cause a timeout here
 532         */
 533        flag = disable_interrupts ();
 534
 535        *addr = 0x00400040;
 536        *addr = data;
 537
 538        /* re-enable interrupts if necessary
 539         */
 540        if (flag)
 541                enable_interrupts ();
 542
 543        start = get_timer (0);
 544        while ((*addr & 0x00800080) != 0x00800080) {
 545                if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 546                        /* Suspend program
 547                         */
 548                        *addr = 0x00B000B0;
 549                        res = 1;
 550                        goto OUT;
 551                }
 552        }
 553
 554        if (*addr & 0x00220022) {
 555                printf ("*** ERROR: program failed!\n");
 556                res = 1;
 557        }
 558
 559OUT:
 560        /* Clear status register and reset to read mode
 561         */
 562        *addr = 0x00500050;
 563        *addr = 0x00FF00FF;
 564
 565        return (res);
 566}
 567
 568/*-----------------------------------------------------------------------
 569 * Write a byte to Flash, returns:
 570 * 0 - OK
 571 * 1 - write timeout
 572 * 2 - Flash not erased
 573 */
 574static int write_byte (flash_info_t *info, ulong dest, uchar data)
 575{
 576        vu_char *addr = (vu_char *)(info->start[0]);
 577        ulong start;
 578        int flag;
 579
 580        /* Check if Flash is (sufficiently) erased */
 581        if ((*((vu_char *)dest) & data) != data) {
 582                return (2);
 583        }
 584        /* Disable interrupts which might cause a timeout here */
 585        flag = disable_interrupts();
 586
 587        addr[0x0555] = 0xAA;
 588        addr[0x02AA] = 0x55;
 589        addr[0x0555] = 0xA0;
 590
 591        *((vu_char *)dest) = data;
 592
 593        /* re-enable interrupts if necessary */
 594        if (flag)
 595                enable_interrupts();
 596
 597        /* data polling for D7 */
 598        start = get_timer (0);
 599        while ((*((vu_char *)dest) & 0x80) != (data & 0x80)) {
 600                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 601                        return (1);
 602                }
 603        }
 604        return (0);
 605}
 606
 607/*-----------------------------------------------------------------------
 608 */
 609