uboot/board/sbc8260/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Marius Groeger <mgroeger@sysgo.de>
   4 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   5 *
   6 * (C) Copyright 2000
   7 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   8 *
   9 * Flash Routines for AMD 29F080B devices
  10 *
  11 *--------------------------------------------------------------------
  12 * See file CREDITS for list of people who contributed to this
  13 * project.
  14 *
  15 * This program is free software; you can redistribute it and/or
  16 * modify it under the terms of the GNU General Public License as
  17 * published by the Free Software Foundation; either version 2 of
  18 * the License, or (at your option) any later version.
  19 *
  20 * This program is distributed in the hope that it will be useful,
  21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23 * GNU General Public License for more details.
  24 *
  25 * You should have received a copy of the GNU General Public License
  26 * along with this program; if not, write to the Free Software
  27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  28 * MA 02111-1307 USA
  29 */
  30
  31#include <common.h>
  32#include <mpc8xx.h>
  33
  34flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  35
  36/*-----------------------------------------------------------------------
  37 * Functions
  38 */
  39
  40static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  41static int write_word (flash_info_t *info, ulong dest, ulong data);
  42
  43/*-----------------------------------------------------------------------
  44 */
  45
  46unsigned long flash_init (void)
  47{
  48    unsigned long size;
  49    int i;
  50
  51    /* Init: no FLASHes known */
  52    for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  53        flash_info[i].flash_id = FLASH_UNKNOWN;
  54    }
  55
  56    /* for now, only support the 4 MB Flash SIMM */
  57    size = flash_get_size((vu_long *)CONFIG_SYS_FLASH0_BASE, &flash_info[0]);
  58
  59    /*
  60     * protect monitor and environment sectors
  61     */
  62
  63#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH0_BASE
  64    flash_protect(FLAG_PROTECT_SET,
  65                  CONFIG_SYS_MONITOR_BASE,
  66                  CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  67                  &flash_info[0]);
  68#endif
  69
  70#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
  71# ifndef  CONFIG_ENV_SIZE
  72#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
  73# endif
  74    flash_protect(FLAG_PROTECT_SET,
  75                  CONFIG_ENV_ADDR,
  76                  CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
  77                  &flash_info[0]);
  78#endif
  79
  80    return /*size*/ (CONFIG_SYS_FLASH0_SIZE * 1024 * 1024);
  81}
  82
  83/*-----------------------------------------------------------------------
  84 */
  85void flash_print_info  (flash_info_t *info)
  86{
  87    int i;
  88
  89    if (info->flash_id == FLASH_UNKNOWN) {
  90        printf ("missing or unknown FLASH type\n");
  91        return;
  92    }
  93
  94    switch ((info->flash_id >> 16) & 0xff) {
  95    case 0x1:
  96        printf ("AMD ");
  97        break;
  98    default:
  99        printf ("Unknown Vendor ");
 100        break;
 101    }
 102
 103    switch (info->flash_id & FLASH_TYPEMASK) {
 104    case AMD_ID_F040B:
 105        printf ("AM29F040B (4 Mbit)\n");
 106        break;
 107    case AMD_ID_F080B:
 108        printf ("AM29F080B (8 Mbit)\n");
 109        break;
 110    default:
 111        printf ("Unknown Chip Type\n");
 112        break;
 113    }
 114
 115    printf ("  Size: %ld MB in %d Sectors\n",
 116            info->size >> 20, info->sector_count);
 117
 118    printf ("  Sector Start Addresses:");
 119    for (i=0; i<info->sector_count; ++i) {
 120        if ((i % 5) == 0)
 121          printf ("\n   ");
 122        printf (" %08lX%s",
 123                info->start[i],
 124                info->protect[i] ? " (RO)" : "     "
 125                );
 126    }
 127    printf ("\n");
 128    return;
 129}
 130
 131/*
 132 * The following code cannot be run from FLASH!
 133 */
 134
 135static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 136{
 137    short i;
 138    vu_long vendor, devid;
 139    ulong base = (ulong)addr;
 140
 141/*    printf("addr   = %08lx\n", (unsigned long)addr); */
 142
 143    /* Reset and Write auto select command: read Manufacturer ID */
 144    addr[0] = 0xf0f0f0f0;
 145    addr[0x0555] = 0xAAAAAAAA;
 146    addr[0x02AA] = 0x55555555;
 147    addr[0x0555] = 0x90909090;
 148    udelay (1000);
 149
 150    vendor = addr[0];
 151/*    printf("vendor = %08lx\n", vendor); */
 152    if (vendor != 0x01010101) {
 153        info->size = 0;
 154        goto out;
 155    }
 156
 157    devid = addr[1];
 158/*    printf("devid  = %08lx\n", devid); */
 159
 160    if ((devid & 0xff) == AMD_ID_F080B) {
 161        info->flash_id     = (vendor & 0xff) << 16 | AMD_ID_F080B;
 162        /* we have 16 sectors with 64KB each x 4 */
 163        info->sector_count = 16;
 164        info->size         = 4 * info->sector_count * 64*1024;
 165    }
 166    else {
 167        info->size = 0;
 168        goto out;
 169    }
 170
 171    /* check for protected sectors */
 172    for (i = 0; i < info->sector_count; i++) {
 173        /* sector base address */
 174        info->start[i] = base + i * (info->size / info->sector_count);
 175        /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 176        /* D0 = 1 if protected */
 177        addr = (volatile unsigned long *)(info->start[i]);
 178        info->protect[i] = addr[2] & 1;
 179    }
 180
 181    /* reset command */
 182    addr = (vu_long *)info->start[0];
 183
 184out:
 185    addr[0] = 0xf0f0f0f0;
 186
 187    return info->size;
 188}
 189
 190
 191/*-----------------------------------------------------------------------
 192 */
 193
 194int flash_erase (flash_info_t *info, int s_first, int s_last)
 195{
 196    vu_long *addr = (vu_long*)(info->start[0]);
 197    int flag, prot, sect, l_sect;
 198    ulong start, now, last;
 199
 200    if ((s_first < 0) || (s_first > s_last)) {
 201        if (info->flash_id == FLASH_UNKNOWN) {
 202            printf ("- missing\n");
 203        } else {
 204            printf ("- no sectors to erase\n");
 205        }
 206        return 1;
 207    }
 208
 209    prot = 0;
 210    for (sect = s_first; sect <= s_last; sect++) {
 211        if (info->protect[sect]) {
 212            prot++;
 213        }
 214    }
 215
 216    if (prot) {
 217        printf ("- Warning: %d protected sectors will not be erased!\n",
 218                prot);
 219    } else {
 220        printf ("\n");
 221    }
 222
 223    l_sect = -1;
 224
 225    /* Disable interrupts which might cause a timeout here */
 226    flag = disable_interrupts();
 227
 228    addr[0x0555] = 0xAAAAAAAA;
 229    addr[0x02AA] = 0x55555555;
 230    addr[0x0555] = 0x80808080;
 231    addr[0x0555] = 0xAAAAAAAA;
 232    addr[0x02AA] = 0x55555555;
 233    udelay (100);
 234
 235    /* Start erase on unprotected sectors */
 236    for (sect = s_first; sect<=s_last; sect++) {
 237        if (info->protect[sect] == 0) { /* not protected */
 238            addr = (vu_long*)(info->start[sect]);
 239            addr[0] = 0x30303030;
 240            l_sect = sect;
 241        }
 242    }
 243
 244    /* re-enable interrupts if necessary */
 245    if (flag)
 246      enable_interrupts();
 247
 248    /* wait at least 80us - let's wait 1 ms */
 249    udelay (1000);
 250
 251    /*
 252     * We wait for the last triggered sector
 253     */
 254    if (l_sect < 0)
 255      goto DONE;
 256
 257    start = get_timer (0);
 258    last  = start;
 259    addr = (vu_long*)(info->start[l_sect]);
 260    while ((addr[0] & 0x80808080) != 0x80808080) {
 261        if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 262            printf ("Timeout\n");
 263            return 1;
 264        }
 265        /* show that we're waiting */
 266        if ((now - last) > 1000) {      /* every second */
 267            serial_putc ('.');
 268            last = now;
 269        }
 270    }
 271
 272    DONE:
 273    /* reset to read mode */
 274    addr = (volatile unsigned long *)info->start[0];
 275    addr[0] = 0xF0F0F0F0;       /* reset bank */
 276
 277    printf (" done\n");
 278    return 0;
 279}
 280
 281/*-----------------------------------------------------------------------
 282 * Copy memory to flash, returns:
 283 * 0 - OK
 284 * 1 - write timeout
 285 * 2 - Flash not erased
 286 */
 287
 288int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 289{
 290    ulong cp, wp, data;
 291    int i, l, rc;
 292
 293    wp = (addr & ~3);   /* get lower word aligned address */
 294
 295    /*
 296     * handle unaligned start bytes
 297     */
 298    if ((l = addr - wp) != 0) {
 299        data = 0;
 300        for (i=0, cp=wp; i<l; ++i, ++cp) {
 301            data = (data << 8) | (*(uchar *)cp);
 302        }
 303        for (; i<4 && cnt>0; ++i) {
 304            data = (data << 8) | *src++;
 305            --cnt;
 306            ++cp;
 307        }
 308        for (; cnt==0 && i<4; ++i, ++cp) {
 309            data = (data << 8) | (*(uchar *)cp);
 310        }
 311
 312        if ((rc = write_word(info, wp, data)) != 0) {
 313            return (rc);
 314        }
 315        wp += 4;
 316    }
 317
 318    /*
 319     * handle word aligned part
 320     */
 321    while (cnt >= 4) {
 322        data = 0;
 323        for (i=0; i<4; ++i) {
 324            data = (data << 8) | *src++;
 325        }
 326        if ((rc = write_word(info, wp, data)) != 0) {
 327            return (rc);
 328        }
 329        wp  += 4;
 330        cnt -= 4;
 331    }
 332
 333    if (cnt == 0) {
 334        return (0);
 335    }
 336
 337    /*
 338     * handle unaligned tail bytes
 339     */
 340    data = 0;
 341    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 342        data = (data << 8) | *src++;
 343        --cnt;
 344    }
 345    for (; i<4; ++i, ++cp) {
 346        data = (data << 8) | (*(uchar *)cp);
 347    }
 348
 349    return (write_word(info, wp, data));
 350}
 351
 352/*-----------------------------------------------------------------------
 353 * Write a word to Flash, returns:
 354 * 0 - OK
 355 * 1 - write timeout
 356 * 2 - Flash not erased
 357 */
 358static int write_word (flash_info_t *info, ulong dest, ulong data)
 359{
 360    vu_long *addr = (vu_long*)(info->start[0]);
 361    ulong start;
 362    int flag;
 363
 364    /* Check if Flash is (sufficiently) erased */
 365    if ((*((vu_long *)dest) & data) != data) {
 366        return (2);
 367    }
 368    /* Disable interrupts which might cause a timeout here */
 369    flag = disable_interrupts();
 370
 371    addr[0x0555] = 0xAAAAAAAA;
 372    addr[0x02AA] = 0x55555555;
 373    addr[0x0555] = 0xA0A0A0A0;
 374
 375    *((vu_long *)dest) = data;
 376
 377    /* re-enable interrupts if necessary */
 378    if (flag)
 379      enable_interrupts();
 380
 381    /* data polling for D7 */
 382    start = get_timer (0);
 383    while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
 384        if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 385            return (1);
 386        }
 387    }
 388    return (0);
 389}
 390
 391/*-----------------------------------------------------------------------
 392 */
 393