uboot/board/emk/common/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * (C) Copyright 2003
   6 * Reinhard Meyer, EMK Elektronik GmbH, r.meyer@emk-elektronik.de
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12
  13flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  14
  15#if defined (CONFIG_TOP860)
  16  typedef unsigned short FLASH_PORT_WIDTH;
  17  typedef volatile unsigned short FLASH_PORT_WIDTHV;
  18  #define       FLASH_ID_MASK   0xFF
  19
  20  #define FPW   FLASH_PORT_WIDTH
  21  #define FPWV  FLASH_PORT_WIDTHV
  22
  23  #define FLASH_CYCLE1  0x0555
  24  #define FLASH_CYCLE2  0x02aa
  25  #define FLASH_ID1             0
  26  #define FLASH_ID2             1
  27  #define FLASH_ID3             0x0e
  28  #define FLASH_ID4             0x0F
  29#endif
  30
  31#if defined (CONFIG_TOP5200) && !defined (CONFIG_LITE5200)
  32  typedef unsigned char FLASH_PORT_WIDTH;
  33  typedef volatile unsigned char FLASH_PORT_WIDTHV;
  34  #define       FLASH_ID_MASK   0xFF
  35
  36  #define FPW   FLASH_PORT_WIDTH
  37  #define FPWV  FLASH_PORT_WIDTHV
  38
  39  #define FLASH_CYCLE1  0x0aaa
  40  #define FLASH_CYCLE2  0x0555
  41  #define FLASH_ID1             0
  42  #define FLASH_ID2             2
  43  #define FLASH_ID3             0x1c
  44  #define FLASH_ID4             0x1E
  45#endif
  46
  47#if defined (CONFIG_TOP5200) && defined (CONFIG_LITE5200)
  48  typedef unsigned char FLASH_PORT_WIDTH;
  49  typedef volatile unsigned char FLASH_PORT_WIDTHV;
  50  #define       FLASH_ID_MASK   0xFF
  51
  52  #define FPW   FLASH_PORT_WIDTH
  53  #define FPWV  FLASH_PORT_WIDTHV
  54
  55  #define FLASH_CYCLE1  0x0555
  56  #define FLASH_CYCLE2  0x02aa
  57  #define FLASH_ID1             0
  58  #define FLASH_ID2             1
  59  #define FLASH_ID3             0x0E
  60  #define FLASH_ID4             0x0F
  61#endif
  62
  63/*-----------------------------------------------------------------------
  64 * Functions
  65 */
  66static ulong flash_get_size(FPWV *addr, flash_info_t *info);
  67static void flash_reset(flash_info_t *info);
  68static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
  69flash_info_t *flash_get_info(ulong base);
  70
  71/*-----------------------------------------------------------------------
  72 * flash_init()
  73 *
  74 * sets up flash_info and returns size of FLASH (bytes)
  75 */
  76unsigned long flash_init (void)
  77{
  78        unsigned long size = 0;
  79        int i = 0;
  80        extern void flash_preinit(void);
  81        extern void flash_afterinit(uint, ulong, ulong);
  82        ulong flashbase = CONFIG_SYS_FLASH_BASE;
  83
  84        flash_preinit();
  85
  86        /* There is only ONE FLASH device */
  87        memset(&flash_info[i], 0, sizeof(flash_info_t));
  88        flash_info[i].size =
  89                        flash_get_size((FPW *)flashbase, &flash_info[i]);
  90        size += flash_info[i].size;
  91
  92#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  93        /* monitor protection ON by default */
  94        flash_protect(FLAG_PROTECT_SET,
  95                      CONFIG_SYS_MONITOR_BASE,
  96                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  97                      flash_get_info(CONFIG_SYS_MONITOR_BASE));
  98#endif
  99
 100#ifdef  CONFIG_ENV_IS_IN_FLASH
 101        /* ENV protection ON by default */
 102        flash_protect(FLAG_PROTECT_SET,
 103                      CONFIG_ENV_ADDR,
 104                      CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
 105                      flash_get_info(CONFIG_ENV_ADDR));
 106#endif
 107
 108
 109        flash_afterinit(i, flash_info[i].start[0], flash_info[i].size);
 110        return size ? size : 1;
 111}
 112
 113/*-----------------------------------------------------------------------
 114 */
 115static void flash_reset(flash_info_t *info)
 116{
 117        FPWV *base = (FPWV *)(info->start[0]);
 118
 119        /* Put FLASH back in read mode */
 120        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
 121                *base = (FPW)0x00FF00FF;        /* Intel Read Mode */
 122        else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
 123                *base = (FPW)0x00F000F0;        /* AMD Read Mode */
 124}
 125
 126/*-----------------------------------------------------------------------
 127 */
 128
 129flash_info_t *flash_get_info(ulong base)
 130{
 131        int i;
 132        flash_info_t * info;
 133
 134        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
 135                info = & flash_info[i];
 136                if (info->size &&
 137                        info->start[0] <= base && base <= info->start[0] + info->size - 1)
 138                        break;
 139        }
 140
 141        return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
 142}
 143
 144/*-----------------------------------------------------------------------
 145 */
 146
 147void flash_print_info (flash_info_t *info)
 148{
 149        int i;
 150        uchar *boottype;
 151        uchar *bootletter;
 152        char *fmt;
 153        uchar botbootletter[] = "B";
 154        uchar topbootletter[] = "T";
 155        uchar botboottype[] = "bottom boot sector";
 156        uchar topboottype[] = "top boot sector";
 157
 158        if (info->flash_id == FLASH_UNKNOWN) {
 159                printf ("missing or unknown FLASH type\n");
 160                return;
 161        }
 162
 163        switch (info->flash_id & FLASH_VENDMASK) {
 164        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 165#if 0
 166        case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
 167        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
 168        case FLASH_MAN_SST:     printf ("SST ");                break;
 169        case FLASH_MAN_STM:     printf ("STM ");                break;
 170        case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
 171#endif
 172        default:                printf ("Unknown Vendor ");     break;
 173        }
 174
 175        /* check for top or bottom boot, if it applies */
 176        if (info->flash_id & FLASH_BTYPE) {
 177                boottype = botboottype;
 178                bootletter = botbootletter;
 179        }
 180        else {
 181                boottype = topboottype;
 182                bootletter = topbootletter;
 183        }
 184
 185        switch (info->flash_id & FLASH_TYPEMASK) {
 186        case FLASH_AM160T:
 187        case FLASH_AM160B:
 188                fmt = "29LV160%s (16 Mbit, %s)\n";
 189                break;
 190        case FLASH_AMLV640U:
 191                fmt = "29LV640M (64 Mbit)\n";
 192                break;
 193        case FLASH_AMDLV065D:
 194                fmt = "29LV065D (64 Mbit)\n";
 195                break;
 196        case FLASH_AMLV256U:
 197                fmt = "29LV256M (256 Mbit)\n";
 198                break;
 199        default:
 200                fmt = "Unknown Chip Type\n";
 201                break;
 202        }
 203
 204        printf (fmt, bootletter, boottype);
 205
 206        printf ("  Size: %ld MB in %d Sectors\n",
 207                info->size >> 20,
 208                info->sector_count);
 209
 210        printf ("  Sector Start Addresses:");
 211
 212        for (i=0; i<info->sector_count; ++i) {
 213                ulong   size;
 214                int             erased;
 215                ulong   *flash = (unsigned long *) info->start[i];
 216
 217                if ((i % 5) == 0) {
 218                        printf ("\n   ");
 219                }
 220
 221                /*
 222                 * Check if whole sector is erased
 223                 */
 224                size =
 225                        (i != (info->sector_count - 1)) ?
 226                        (info->start[i + 1] - info->start[i]) >> 2 :
 227                (info->start[0] + info->size - info->start[i]) >> 2;
 228
 229                for (
 230                        flash = (unsigned long *) info->start[i], erased = 1;
 231                                (flash != (unsigned long *) info->start[i] + size) && erased;
 232                                        flash++
 233                        )
 234                        erased = *flash == ~0x0UL;
 235
 236                printf (" %08lX %s %s",
 237                        info->start[i],
 238                        erased ? "E": " ",
 239                        info->protect[i] ? "(RO)" : "    ");
 240        }
 241
 242        printf ("\n");
 243}
 244
 245/*-----------------------------------------------------------------------
 246 */
 247
 248/*
 249 * The following code cannot be run from FLASH!
 250 */
 251
 252ulong flash_get_size (FPWV *addr, flash_info_t *info)
 253{
 254        int             i;
 255
 256        /* Write auto select command: read Manufacturer ID */
 257        /* Write auto select command sequence and test FLASH answer */
 258        addr[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* for AMD, Intel ignores this */
 259        addr[FLASH_CYCLE2] = (FPW)0x00550055;   /* for AMD, Intel ignores this */
 260        addr[FLASH_CYCLE1] = (FPW)0x00900090;   /* selects Intel or AMD */
 261
 262        /* The manufacturer codes are only 1 byte, so just use 1 byte.
 263         * This works for any bus width and any FLASH device width.
 264         */
 265        udelay(100);
 266        switch (addr[FLASH_ID1] & 0xff) {
 267
 268        case (uchar)AMD_MANUFACT:
 269                info->flash_id = FLASH_MAN_AMD;
 270                break;
 271
 272#if 0
 273        case (uchar)INTEL_MANUFACT:
 274                info->flash_id = FLASH_MAN_INTEL;
 275                break;
 276#endif
 277
 278        default:
 279                printf ("unknown vendor=%x ", addr[FLASH_ID1] & 0xff);
 280                info->flash_id = FLASH_UNKNOWN;
 281                info->sector_count = 0;
 282                info->size = 0;
 283                break;
 284        }
 285
 286        /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
 287        if (info->flash_id != FLASH_UNKNOWN) switch ((FPW)addr[FLASH_ID2]) {
 288
 289        case (FPW)AMD_ID_LV160B:
 290                info->flash_id += FLASH_AM160B;
 291                info->sector_count = 35;
 292                info->size = 0x00200000;
 293                info->start[0] = (ulong)addr;
 294                info->start[1] = (ulong)addr + 0x4000;
 295                info->start[2] = (ulong)addr + 0x6000;
 296                info->start[3] = (ulong)addr + 0x8000;
 297                for (i = 4; i < info->sector_count; i++)
 298                {
 299                        info->start[i] = (ulong)addr + 0x10000 * (i-3);
 300                }
 301                break;
 302
 303        case (FPW)AMD_ID_LV065D:
 304                info->flash_id += FLASH_AMDLV065D;
 305                info->sector_count = 128;
 306                info->size = 0x00800000;
 307                for (i = 0; i < info->sector_count; i++)
 308                {
 309                        info->start[i] = (ulong)addr + 0x10000 * i;
 310                }
 311                break;
 312
 313        case (FPW)AMD_ID_MIRROR:
 314                /* MIRROR BIT FLASH, read more ID bytes */
 315                if ((FPW)addr[FLASH_ID3] == (FPW)AMD_ID_LV640U_2 &&
 316                        (FPW)addr[FLASH_ID4] == (FPW)AMD_ID_LV640U_3)
 317                {
 318                        info->flash_id += FLASH_AMLV640U;
 319                        info->sector_count = 128;
 320                        info->size = 0x00800000;
 321                        for (i = 0; i < info->sector_count; i++)
 322                        {
 323                                info->start[i] = (ulong)addr + 0x10000 * i;
 324                        }
 325                        break;
 326                }
 327                if ((FPW)addr[FLASH_ID3] == (FPW)AMD_ID_LV256U_2 &&
 328                        (FPW)addr[FLASH_ID4] == (FPW)AMD_ID_LV256U_3)
 329                {
 330                        /* attention: only the first 16 MB will be used in u-boot */
 331                        info->flash_id += FLASH_AMLV256U;
 332                        info->sector_count = 256;
 333                        info->size = 0x01000000;
 334                        for (i = 0; i < info->sector_count; i++)
 335                        {
 336                                info->start[i] = (ulong)addr + 0x10000 * i;
 337                        }
 338                        break;
 339                }
 340
 341                /* fall thru to here ! */
 342        default:
 343                printf ("unknown AMD device=%x %x %x",
 344                        (FPW)addr[FLASH_ID2],
 345                        (FPW)addr[FLASH_ID3],
 346                        (FPW)addr[FLASH_ID4]);
 347                info->flash_id = FLASH_UNKNOWN;
 348                info->sector_count = 0;
 349                info->size = 0x800000;
 350                break;
 351        }
 352
 353        /* Put FLASH back in read mode */
 354        flash_reset(info);
 355
 356        return (info->size);
 357}
 358
 359/*-----------------------------------------------------------------------
 360 */
 361
 362int     flash_erase (flash_info_t *info, int s_first, int s_last)
 363{
 364        FPWV *addr;
 365        int flag, prot, sect;
 366        int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
 367        ulong start, now, last;
 368        int rcode = 0;
 369
 370        if ((s_first < 0) || (s_first > s_last)) {
 371                if (info->flash_id == FLASH_UNKNOWN) {
 372                        printf ("- missing\n");
 373                } else {
 374                        printf ("- no sectors to erase\n");
 375                }
 376                return 1;
 377        }
 378
 379        switch (info->flash_id & FLASH_TYPEMASK) {
 380        case FLASH_AM160B:
 381        case FLASH_AMLV640U:
 382                break;
 383        case FLASH_UNKNOWN:
 384        default:
 385                printf ("Can't erase unknown flash type %08lx - aborted\n",
 386                        info->flash_id);
 387                return 1;
 388        }
 389
 390        prot = 0;
 391        for (sect=s_first; sect<=s_last; ++sect) {
 392                if (info->protect[sect]) {
 393                        prot++;
 394                }
 395        }
 396
 397        if (prot) {
 398                printf ("- Warning: %d protected sectors will not be erased!\n",
 399                        prot);
 400        } else {
 401                printf ("\n");
 402        }
 403
 404        last  = get_timer(0);
 405
 406        /* Start erase on unprotected sectors */
 407        for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
 408
 409                if (info->protect[sect] != 0)   /* protected, skip it */
 410                        continue;
 411
 412                /* Disable interrupts which might cause a timeout here */
 413                flag = disable_interrupts();
 414
 415                addr = (FPWV *)(info->start[sect]);
 416                if (intel) {
 417                        *addr = (FPW)0x00500050; /* clear status register */
 418                        *addr = (FPW)0x00200020; /* erase setup */
 419                        *addr = (FPW)0x00D000D0; /* erase confirm */
 420                }
 421                else {
 422                        /* must be AMD style if not Intel */
 423                        FPWV *base;             /* first address in bank */
 424
 425                        base = (FPWV *)(info->start[0]);
 426                        base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
 427                        base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
 428                        base[FLASH_CYCLE1] = (FPW)0x00800080;   /* erase mode */
 429                        base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
 430                        base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
 431                        *addr = (FPW)0x00300030;        /* erase sector */
 432                }
 433
 434                /* re-enable interrupts if necessary */
 435                if (flag)
 436                        enable_interrupts();
 437
 438                start = get_timer(0);
 439
 440                /* wait at least 50us for AMD, 80us for Intel.
 441                 * Let's wait 1 ms.
 442                 */
 443                udelay (1000);
 444
 445                while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
 446                        if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 447                                printf ("Timeout\n");
 448
 449                                if (intel) {
 450                                        /* suspend erase        */
 451                                        *addr = (FPW)0x00B000B0;
 452                                }
 453
 454                                flash_reset(info);      /* reset to read mode */
 455                                rcode = 1;              /* failed */
 456                                break;
 457                        }
 458
 459                        /* show that we're waiting */
 460                        if ((get_timer(last)) > CONFIG_SYS_HZ) {/* every second */
 461                                putc ('.');
 462                                last = get_timer(0);
 463                        }
 464                }
 465
 466                /* show that we're waiting */
 467                if ((get_timer(last)) > CONFIG_SYS_HZ) {        /* every second */
 468                        putc ('.');
 469                        last = get_timer(0);
 470                }
 471
 472                flash_reset(info);      /* reset to read mode */
 473        }
 474
 475        printf (" done\n");
 476        return rcode;
 477}
 478
 479/*-----------------------------------------------------------------------
 480 * Copy memory to flash, returns:
 481 * 0 - OK
 482 * 1 - write timeout
 483 * 2 - Flash not erased
 484 */
 485int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 486{
 487        FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
 488        int bytes;        /* number of bytes to program in current word         */
 489        int left;         /* number of bytes left to program                    */
 490        int i, res;
 491
 492        for (left = cnt, res = 0;
 493                 left > 0 && res == 0;
 494                 addr += sizeof(data), left -= sizeof(data) - bytes) {
 495
 496                bytes = addr & (sizeof(data) - 1);
 497                addr &= ~(sizeof(data) - 1);
 498
 499                /* combine source and destination data so can program
 500                 * an entire word of 16 or 32 bits
 501                 */
 502                for (i = 0; i < sizeof(data); i++) {
 503                        data <<= 8;
 504                        if (i < bytes || i - bytes >= left )
 505                                data += *((uchar *)addr + i);
 506                        else
 507                                data += *src++;
 508                }
 509
 510                /* write one word to the flash */
 511                switch (info->flash_id & FLASH_VENDMASK) {
 512                case FLASH_MAN_AMD:
 513                        res = write_word_amd(info, (FPWV *)addr, data);
 514                        break;
 515                default:
 516                        /* unknown flash type, error! */
 517                        printf ("missing or unknown FLASH type\n");
 518                        res = 1;        /* not really a timeout, but gives error */
 519                        break;
 520                }
 521        }
 522
 523        return (res);
 524}
 525
 526/*-----------------------------------------------------------------------
 527 * Write a word to Flash for AMD FLASH
 528 * A word is 16 or 32 bits, whichever the bus width of the flash bank
 529 * (not an individual chip) is.
 530 *
 531 * returns:
 532 * 0 - OK
 533 * 1 - write timeout
 534 * 2 - Flash not erased
 535 */
 536static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
 537{
 538        ulong start;
 539        int flag;
 540        int res = 0;    /* result, assume success       */
 541        FPWV *base;             /* first address in flash bank  */
 542
 543        /* Check if Flash is (sufficiently) erased */
 544        if ((*dest & data) != data) {
 545                return (2);
 546        }
 547
 548
 549        base = (FPWV *)(info->start[0]);
 550
 551        /* Disable interrupts which might cause a timeout here */
 552        flag = disable_interrupts();
 553
 554        base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
 555        base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
 556        base[FLASH_CYCLE1] = (FPW)0x00A000A0;   /* selects program mode */
 557
 558        *dest = data;           /* start programming the data   */
 559
 560        /* re-enable interrupts if necessary */
 561        if (flag)
 562                enable_interrupts();
 563
 564        start = get_timer (0);
 565
 566        /* data polling for D7 */
 567        while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
 568                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 569                        *dest = (FPW)0x00F000F0;        /* reset bank */
 570                        res = 1;
 571                }
 572        }
 573
 574        return (res);
 575}
 576