uboot/board/eltec/elppc/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 * 07-10-2002 Frank Gottschling: added 29F032 flash (ELPPC).
  10 *        fixed monitor protection part
  11 *
  12 * 09-18-2001 Andreas Heppel: Reduced the code in here to the usage
  13 *        of AMD's 29F040 and 29F016 flashes, since the BAB7xx does use
  14 *        any other.
  15 */
  16
  17#include <common.h>
  18#include <asm/processor.h>
  19#include <asm/pci_io.h>
  20
  21flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  22
  23ulong flash_get_size (vu_long *addr, flash_info_t *info);
  24static int write_word (flash_info_t *info, ulong dest, ulong data);
  25
  26/*flash command address offsets*/
  27
  28#define ADDR0           (0x555)
  29#define ADDR1           (0x2AA)
  30#define ADDR3           (0x001)
  31
  32#define FLASH_WORD_SIZE unsigned char
  33
  34/*----------------------------------------------------------------------------*/
  35
  36unsigned long flash_init (void)
  37{
  38    unsigned long size1, size2;
  39    int i;
  40
  41    /* Init: no FLASHes known */
  42    for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i)
  43    {
  44        flash_info[i].flash_id = FLASH_UNKNOWN;
  45    }
  46
  47    /* initialise 1st flash */
  48    size1 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
  49
  50    if (flash_info[0].flash_id == FLASH_UNKNOWN)
  51    {
  52        printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
  53            size1, size1<<20);
  54    }
  55
  56    /* initialise 2nd flash */
  57    size2 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
  58
  59    if (flash_info[1].flash_id == FLASH_UNKNOWN)
  60    {
  61        printf ("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
  62            size2, size2<<20);
  63    }
  64
  65    /* monitor protection ON by default */
  66    if (size1 == 512*1024)
  67    {
  68        (void)flash_protect(FLAG_PROTECT_SET,
  69                FLASH_BASE0_PRELIM,
  70                FLASH_BASE0_PRELIM+monitor_flash_len-1,
  71                &flash_info[0]);
  72    }
  73    if (size2 == 512*1024)
  74    {
  75        (void)flash_protect(FLAG_PROTECT_SET,
  76                FLASH_BASE1_PRELIM,
  77                FLASH_BASE1_PRELIM+monitor_flash_len-1,
  78                &flash_info[1]);
  79    }
  80    if (size2 == 4*1024*1024)
  81    {
  82        (void)flash_protect(FLAG_PROTECT_SET,
  83                CONFIG_SYS_FLASH_BASE,
  84                CONFIG_SYS_FLASH_BASE+monitor_flash_len-1,
  85                &flash_info[1]);
  86    }
  87
  88    return (size1 + size2);
  89}
  90
  91/*----------------------------------------------------------------------------*/
  92
  93void flash_print_info  (flash_info_t *info)
  94{
  95    int i;
  96    int k;
  97    int size;
  98    int erased;
  99    volatile unsigned long *flash;
 100
 101    if (info->flash_id == FLASH_UNKNOWN) {
 102        printf ("missing or unknown FLASH type\n");
 103        flash_init();
 104    }
 105
 106    if (info->flash_id == FLASH_UNKNOWN) {
 107        printf ("missing or unknown FLASH type\n");
 108        return;
 109    }
 110
 111    switch (info->flash_id & FLASH_VENDMASK) {
 112    case FLASH_MAN_AMD:
 113        printf ("AMD ");
 114        break;
 115    default:
 116        printf ("Unknown Vendor ");
 117        break;
 118    }
 119
 120    switch (info->flash_id & FLASH_TYPEMASK) {
 121    case AMD_ID_F040B:
 122        printf ("AM29F040B (4 Mbit)\n");
 123        break;
 124    case AMD_ID_F016D:
 125        printf ("AM29F016D (16 Mbit)\n");
 126        break;
 127    case AMD_ID_F032B:
 128        printf ("AM29F032B (32 Mbit)\n");
 129        break;
 130   default:
 131        printf ("Unknown Chip Type\n");
 132        break;
 133    }
 134
 135    if (info->size >= (1 << 20)) {
 136        printf ("  Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count);
 137    } else {
 138        printf ("  Size: %ld kB in %d Sectors\n", info->size >> 10, info->sector_count);
 139    }
 140
 141    printf ("  Sector Start Addresses:");
 142    for (i=0; i<info->sector_count; ++i) {
 143        /*
 144        * Check if whole sector is erased
 145        */
 146        if (i != (info->sector_count-1))
 147            size = info->start[i+1] - info->start[i];
 148        else
 149            size = info->start[0] + info->size - info->start[i];
 150
 151        erased = 1;
 152        flash = (volatile unsigned long *)info->start[i];
 153        size = size >> 2;        /* divide by 4 for longword access */
 154        for (k=0; k<size; k++) {
 155            if (*flash++ != 0xffffffff) {
 156                erased = 0;
 157                break;
 158            }
 159        }
 160
 161        if ((i % 5) == 0)
 162            printf ("\n   ");
 163
 164        printf (" %08lX%s%s",
 165            info->start[i],
 166            erased ? " E" : "  ",
 167            info->protect[i] ? "RO " : "   ");
 168    }
 169    printf ("\n");
 170}
 171
 172/*----------------------------------------------------------------------------*/
 173/*
 174 * The following code cannot be run from FLASH!
 175 */
 176ulong flash_get_size (vu_long *addr, flash_info_t *info)
 177{
 178    short i;
 179    ulong vendor, devid;
 180    ulong base = (ulong)addr;
 181    volatile unsigned char *caddr = (unsigned char *)addr;
 182
 183#ifdef DEBUG
 184    printf("flash_get_size for address 0x%lx: \n", (unsigned long)caddr);
 185#endif
 186
 187    /* Write auto select command: read Manufacturer ID */
 188    caddr[0] = 0xF0;   /* reset bank */
 189    udelay(10);
 190
 191    eieio();
 192    caddr[0x555] = 0xAA;
 193    udelay(10);
 194    caddr[0x2AA] = 0x55;
 195    udelay(10);
 196    caddr[0x555] = 0x90;
 197
 198    udelay(10);
 199
 200    vendor = caddr[0];
 201    devid = caddr[1];
 202
 203#ifdef DEBUG
 204    printf("Manufacturer: 0x%lx\n", vendor);
 205#endif
 206
 207    vendor &= 0xff;
 208    devid &= 0xff;
 209
 210    /* We accept only two AMD types */
 211    switch (vendor) {
 212    case (FLASH_WORD_SIZE)AMD_MANUFACT:
 213        info->flash_id = FLASH_MAN_AMD;
 214        break;
 215    default:
 216        info->flash_id = FLASH_UNKNOWN;
 217        info->sector_count = 0;
 218        info->size = 0;
 219        return (0);         /* no or unknown flash  */
 220    }
 221
 222    switch (devid) {
 223    case (FLASH_WORD_SIZE)AMD_ID_F040B:
 224        info->flash_id |= AMD_ID_F040B;
 225        info->sector_count = 8;
 226        info->size = 0x00080000;
 227        break;              /* => 0.5 MB      */
 228
 229    case (FLASH_WORD_SIZE)AMD_ID_F016D:
 230        info->flash_id |= AMD_ID_F016D;
 231        info->sector_count = 32;
 232        info->size         = 0x00200000;
 233        break;              /* => 2 MB      */
 234
 235    case (FLASH_WORD_SIZE)AMD_ID_F032B:
 236        info->flash_id |= AMD_ID_F032B;
 237        info->sector_count = 64;
 238        info->size         = 0x00400000;
 239        break;              /* => 4 MB      */
 240
 241    default:
 242        info->flash_id = FLASH_UNKNOWN;
 243        return (0);         /* => no or unknown flash */
 244
 245    }
 246
 247#ifdef DEBUG
 248    printf("flash id 0x%lx; sector count 0x%x, size 0x%lx\n", info->flash_id, info->sector_count, info->size);
 249#endif
 250
 251    /* check for protected sectors */
 252    for (i = 0; i < info->sector_count; i++) {
 253        /* sector base address */
 254        info->start[i] = base + i * (info->size / info->sector_count);
 255        /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 256        /* D0 = 1 if protected */
 257        caddr = (volatile unsigned char *)(info->start[i]);
 258        info->protect[i] = caddr[2] & 1;
 259    }
 260
 261    /*
 262     * Prevent writes to uninitialized FLASH.
 263     */
 264    if (info->flash_id != FLASH_UNKNOWN) {
 265        caddr = (volatile unsigned char *)info->start[0];
 266        caddr[0] = 0xF0;   /* reset bank */
 267    }
 268
 269    return (info->size);
 270}
 271
 272/*----------------------------------------------------------------------------*/
 273
 274int flash_erase (flash_info_t *info, int s_first, int s_last)
 275{
 276    volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
 277    int flag, prot, sect, l_sect;
 278    ulong start, now, last;
 279    int rc = 0;
 280
 281    if ((s_first < 0) || (s_first > s_last)) {
 282        if (info->flash_id == FLASH_UNKNOWN) {
 283            printf ("- missing\n");
 284        } else {
 285            printf ("- no sectors to erase\n");
 286        }
 287        return 1;
 288    }
 289
 290    if ((info->flash_id == FLASH_UNKNOWN) ||
 291        (info->flash_id > FLASH_AMD_COMP)) {
 292        printf ("Can't erase unknown flash type - aborted\n");
 293        return 1;
 294    }
 295
 296    prot = 0;
 297    for (sect=s_first; sect<=s_last; ++sect) {
 298        if (info->protect[sect]) {
 299            prot++;
 300        }
 301    }
 302
 303    if (prot) {
 304        printf ("- Warning: %d protected sectors will not be erased!\n",
 305            prot);
 306    } else {
 307        printf ("\n");
 308    }
 309
 310    l_sect = -1;
 311
 312    /* Disable interrupts which might cause a timeout here */
 313    flag = disable_interrupts();
 314
 315    addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 316    addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 317    addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
 318    addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 319    addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 320
 321    /* Start erase on unprotected sectors */
 322    for (sect = s_first; sect<=s_last; sect++) {
 323        if (info->protect[sect] == 0) { /* not protected */
 324            addr = (FLASH_WORD_SIZE *)(info->start[sect]);
 325            if (info->flash_id & FLASH_MAN_SST) {
 326                addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 327                addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 328                addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
 329                addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 330                addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 331                addr[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
 332                udelay(30000);  /* wait 30 ms */
 333            }
 334            else
 335                addr[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
 336            l_sect = sect;
 337        }
 338    }
 339
 340    /* re-enable interrupts if necessary */
 341    if (flag)
 342        enable_interrupts();
 343
 344    /* wait at least 80us - let's wait 1 ms */
 345    udelay (1000);
 346
 347    /*
 348     * We wait for the last triggered sector
 349     */
 350    if (l_sect < 0)
 351        goto DONE;
 352
 353    start = get_timer (0);
 354    last  = start;
 355    addr = (FLASH_WORD_SIZE *)(info->start[l_sect]);
 356    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
 357        if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 358            printf ("Timeout\n");
 359            return 1;
 360        }
 361        /* show that we're waiting */
 362        if ((now - last) > 1000) {  /* every second */
 363            serial_putc ('.');
 364            last = now;
 365        }
 366    }
 367
 368DONE:
 369    /* reset to read mode */
 370    addr = (FLASH_WORD_SIZE *)info->start[0];
 371    addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
 372
 373    printf (" done\n");
 374    return rc;
 375}
 376
 377/*----------------------------------------------------------------------------*/
 378/*
 379 * Copy memory to flash, returns:
 380 * 0 - OK
 381 * 1 - write timeout
 382 * 2 - Flash not erased
 383 */
 384int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 385{
 386    ulong cp, wp, data;
 387    int i, l, rc;
 388
 389    wp = (addr & ~3);   /* get lower word aligned address */
 390
 391    /*
 392     * handle unaligned start bytes
 393     */
 394    if ((l = addr - wp) != 0) {
 395        data = 0;
 396        for (i=0, cp=wp; i<l; ++i, ++cp) {
 397            data = (data << 8) | (*(uchar *)cp);
 398        }
 399        for (; i<4 && cnt>0; ++i) {
 400            data = (data << 8) | *src++;
 401            --cnt;
 402            ++cp;
 403        }
 404        for (; cnt==0 && i<4; ++i, ++cp) {
 405            data = (data << 8) | (*(uchar *)cp);
 406        }
 407
 408        if ((rc = write_word(info, wp, data)) != 0) {
 409            return (rc);
 410        }
 411        wp += 4;
 412    }
 413
 414    /*
 415     * handle word aligned part
 416     */
 417    while (cnt >= 4) {
 418        data = 0;
 419        for (i=0; i<4; ++i) {
 420            data = (data << 8) | *src++;
 421        }
 422        if ((rc = write_word(info, wp, data)) != 0) {
 423            return (rc);
 424        }
 425        wp  += 4;
 426        cnt -= 4;
 427    }
 428
 429    if (cnt == 0) {
 430        return (0);
 431    }
 432
 433    /*
 434     * handle unaligned tail bytes
 435     */
 436    data = 0;
 437    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 438        data = (data << 8) | *src++;
 439        --cnt;
 440    }
 441    for (; i<4; ++i, ++cp) {
 442        data = (data << 8) | (*(uchar *)cp);
 443    }
 444
 445    return (write_word(info, wp, data));
 446}
 447
 448/*----------------------------------------------------------------------------*/
 449/* Write a word to Flash, returns:
 450 * 0 - OK
 451 * 1 - write timeout
 452 * 2 - Flash not erased
 453 */
 454static int write_word (flash_info_t *info, ulong dest, ulong data)
 455{
 456        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]);
 457        volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest;
 458        volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
 459    ulong start;
 460    int flag;
 461        int i;
 462
 463    /* Check if Flash is (sufficiently) erased */
 464    if ((*((volatile FLASH_WORD_SIZE *)dest) &
 465             (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
 466        return (2);
 467    }
 468    /* Disable interrupts which might cause a timeout here */
 469    flag = disable_interrupts();
 470
 471        for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
 472          {
 473            addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
 474            addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
 475            addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0;
 476
 477            dest2[i] = data2[i];
 478
 479            /* re-enable interrupts if necessary */
 480            if (flag)
 481              enable_interrupts();
 482
 483            /* data polling for D7 */
 484            start = get_timer (0);
 485            while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) !=
 486                   (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
 487              if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 488                return (1);
 489              }
 490            }
 491          }
 492
 493    return (0);
 494}
 495
 496/*----------------------------------------------------------------------------*/
 497