uboot/board/mbx8xx/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 AM290[48]0B 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#include "vpd.h"
  34
  35flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  36
  37/*-----------------------------------------------------------------------
  38 * Functions
  39 */
  40
  41static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  42static int write_word (flash_info_t *info, ulong dest, ulong data);
  43
  44/*-----------------------------------------------------------------------
  45 */
  46
  47unsigned long flash_init (void)
  48{
  49    unsigned long size, totsize;
  50    int i;
  51    ulong addr;
  52
  53    /* Init: no FLASHes known */
  54    for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  55        flash_info[i].flash_id = FLASH_UNKNOWN;
  56    }
  57
  58    totsize = 0;
  59    addr = 0xfc000000;
  60    for(i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  61        size = flash_get_size((vu_long *)addr, &flash_info[i]);
  62        if (flash_info[i].flash_id == FLASH_UNKNOWN)
  63          break;
  64        totsize += size;
  65        addr += size;
  66    }
  67
  68    addr = 0xfe000000;
  69    for(i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  70
  71        size = flash_get_size((vu_long *)addr, &flash_info[i]);
  72        if (flash_info[i].flash_id == FLASH_UNKNOWN)
  73          break;
  74        totsize += size;
  75        addr += size;
  76    }
  77
  78#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  79    /* monitor protection ON by default */
  80    flash_protect(FLAG_PROTECT_SET,
  81                  CONFIG_SYS_MONITOR_BASE,
  82                  CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  83                  &flash_info[0]);
  84#endif
  85
  86    return (totsize);
  87}
  88
  89/*-----------------------------------------------------------------------
  90 */
  91void flash_print_info  (flash_info_t *info)
  92{
  93    int i;
  94
  95    if (info->flash_id == FLASH_UNKNOWN) {
  96        printf ("missing or unknown FLASH type\n");
  97        return;
  98    }
  99
 100    switch (info->flash_id >> 16) {
 101    case 0x1:
 102        printf ("AMD ");
 103        break;
 104    default:
 105        printf ("Unknown Vendor ");
 106        break;
 107    }
 108
 109    switch (info->flash_id & FLASH_TYPEMASK) {
 110    case AMD_ID_F040B:
 111        printf ("AM29F040B (4 Mbit)\n");
 112        break;
 113    case AMD_ID_F080B:
 114        printf ("AM29F080B (8 Mbit)\n");
 115        break;
 116    case AMD_ID_F016D:
 117        printf ("AM29F016D (16 Mbit)\n");
 118        break;
 119    default:
 120        printf ("Unknown Chip Type\n");
 121        break;
 122    }
 123
 124    printf ("  Size: %ld MB in %d Sectors\n",
 125            info->size >> 20, info->sector_count);
 126
 127    printf ("  Sector Start Addresses:");
 128    for (i=0; i<info->sector_count; ++i) {
 129        if ((i % 5) == 0)
 130          printf ("\n   ");
 131        printf (" %08lX%s",
 132                info->start[i],
 133                info->protect[i] ? " (RO)" : "     "
 134                );
 135    }
 136    printf ("\n");
 137    return;
 138}
 139
 140/*
 141 * The following code cannot be run from FLASH!
 142 */
 143
 144static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 145{
 146    short i;
 147    ulong vendor, devid;
 148    ulong base = (ulong)addr;
 149
 150    /* Write auto select command: read Manufacturer ID */
 151    addr[0x0555] = 0xAAAAAAAA;
 152    addr[0x02AA] = 0x55555555;
 153    addr[0x0555] = 0x90909090;
 154
 155    vendor = addr[0];
 156    devid = addr[1] & 0xff;
 157
 158    /* only support AMD */
 159    if (vendor != 0x01010101) {
 160        return 0;
 161    }
 162
 163    vendor &= 0xf;
 164    devid &= 0xff;
 165
 166    if (devid == AMD_ID_F040B) {
 167        info->flash_id     = vendor << 16 | devid;
 168        info->sector_count = 8;
 169        info->size         = info->sector_count * 0x10000;
 170    }
 171    else if (devid == AMD_ID_F080B) {
 172        info->flash_id     = vendor << 16 | devid;
 173        info->sector_count = 16;
 174        info->size         = 4 * info->sector_count * 0x10000;
 175    }
 176    else if (devid == AMD_ID_F016D) {
 177        info->flash_id     = vendor << 16 | devid;
 178        info->sector_count = 32;
 179        info->size         = 4 * info->sector_count * 0x10000;
 180    }
 181    else {
 182        printf ("## Unknown Flash Type: %08lx\n", devid);
 183        return 0;
 184    }
 185
 186    /* check for protected sectors */
 187    for (i = 0; i < info->sector_count; i++) {
 188        /* sector base address */
 189        info->start[i] = base + i * (info->size / info->sector_count);
 190        /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 191        /* D0 = 1 if protected */
 192        addr = (volatile unsigned long *)(info->start[i]);
 193        info->protect[i] = addr[2] & 1;
 194    }
 195
 196    /*
 197     * Prevent writes to uninitialized FLASH.
 198     */
 199    if (info->flash_id != FLASH_UNKNOWN) {
 200        addr = (vu_long *)info->start[0];
 201        addr[0] = 0xF0; /* reset bank */
 202    }
 203
 204    return (info->size);
 205}
 206
 207
 208/*-----------------------------------------------------------------------
 209 */
 210
 211int     flash_erase (flash_info_t *info, int s_first, int s_last)
 212{
 213    vu_long *addr = (vu_long*)(info->start[0]);
 214    int flag, prot, sect, l_sect;
 215    ulong start, now, last;
 216
 217    if ((s_first < 0) || (s_first > s_last)) {
 218        if (info->flash_id == FLASH_UNKNOWN) {
 219            printf ("- missing\n");
 220        } else {
 221            printf ("- no sectors to erase\n");
 222        }
 223        return 1;
 224    }
 225
 226    prot = 0;
 227    for (sect = s_first; sect <= s_last; sect++) {
 228        if (info->protect[sect]) {
 229            prot++;
 230        }
 231    }
 232
 233    if (prot) {
 234        printf ("- Warning: %d protected sectors will not be erased!\n",
 235                prot);
 236    } else {
 237        printf ("\n");
 238    }
 239
 240    l_sect = -1;
 241
 242    /* Disable interrupts which might cause a timeout here */
 243    flag = disable_interrupts();
 244
 245    addr[0x0555] = 0XAAAAAAAA;
 246    addr[0x02AA] = 0x55555555;
 247    addr[0x0555] = 0x80808080;
 248    addr[0x0555] = 0XAAAAAAAA;
 249    addr[0x02AA] = 0x55555555;
 250
 251    /* Start erase on unprotected sectors */
 252    for (sect = s_first; sect<=s_last; sect++) {
 253        if (info->protect[sect] == 0) { /* not protected */
 254            addr = (vu_long*)(info->start[sect]);
 255            addr[0] = 0x30303030;
 256            l_sect = sect;
 257        }
 258    }
 259
 260    /* re-enable interrupts if necessary */
 261    if (flag)
 262      enable_interrupts();
 263
 264    /* wait at least 80us - let's wait 1 ms */
 265    udelay (1000);
 266
 267    /*
 268     * We wait for the last triggered sector
 269     */
 270    if (l_sect < 0)
 271      goto DONE;
 272
 273    start = get_timer (0);
 274    last  = start;
 275    addr = (vu_long*)(info->start[l_sect]);
 276    while ((addr[0] & 0x80808080) != 0x80808080) {
 277        if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 278            printf ("Timeout\n");
 279            return 1;
 280        }
 281        /* show that we're waiting */
 282        if ((now - last) > 1000) {      /* every second */
 283            serial_putc ('.');
 284            last = now;
 285        }
 286    }
 287
 288    DONE:
 289    /* reset to read mode */
 290    addr = (volatile unsigned long *)info->start[0];
 291    addr[0] = 0xF0F0F0F0;       /* reset bank */
 292
 293    printf (" done\n");
 294    return 0;
 295}
 296
 297/*-----------------------------------------------------------------------
 298 * Copy memory to flash, returns:
 299 * 0 - OK
 300 * 1 - write timeout
 301 * 2 - Flash not erased
 302 */
 303
 304int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 305{
 306    ulong cp, wp, data;
 307    int i, l, rc;
 308
 309    wp = (addr & ~3);   /* get lower word aligned address */
 310
 311    /*
 312     * handle unaligned start bytes
 313     */
 314    if ((l = addr - wp) != 0) {
 315        data = 0;
 316        for (i=0, cp=wp; i<l; ++i, ++cp) {
 317            data = (data << 8) | (*(uchar *)cp);
 318        }
 319        for (; i<4 && cnt>0; ++i) {
 320            data = (data << 8) | *src++;
 321            --cnt;
 322            ++cp;
 323        }
 324        for (; cnt==0 && i<4; ++i, ++cp) {
 325            data = (data << 8) | (*(uchar *)cp);
 326        }
 327
 328        if ((rc = write_word(info, wp, data)) != 0) {
 329            return (rc);
 330        }
 331        wp += 4;
 332    }
 333
 334    /*
 335     * handle word aligned part
 336     */
 337    while (cnt >= 4) {
 338        data = 0;
 339        for (i=0; i<4; ++i) {
 340            data = (data << 8) | *src++;
 341        }
 342        if ((rc = write_word(info, wp, data)) != 0) {
 343            return (rc);
 344        }
 345        wp  += 4;
 346        cnt -= 4;
 347    }
 348
 349    if (cnt == 0) {
 350        return (0);
 351    }
 352
 353    /*
 354     * handle unaligned tail bytes
 355     */
 356    data = 0;
 357    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 358        data = (data << 8) | *src++;
 359        --cnt;
 360    }
 361    for (; i<4; ++i, ++cp) {
 362        data = (data << 8) | (*(uchar *)cp);
 363    }
 364
 365    return (write_word(info, wp, data));
 366}
 367
 368/*-----------------------------------------------------------------------
 369 * Write a word to Flash, returns:
 370 * 0 - OK
 371 * 1 - write timeout
 372 * 2 - Flash not erased
 373 */
 374static int write_word (flash_info_t *info, ulong dest, ulong data)
 375{
 376    vu_long *addr = (vu_long*)(info->start[0]);
 377    ulong start;
 378    int flag;
 379
 380    /* Check if Flash is (sufficiently) erased */
 381    if ((*((vu_long *)dest) & data) != data) {
 382        return (2);
 383    }
 384    /* Disable interrupts which might cause a timeout here */
 385    flag = disable_interrupts();
 386
 387    addr[0x0555] = 0xAAAAAAAA;
 388    addr[0x02AA] = 0x55555555;
 389    addr[0x0555] = 0xA0A0A0A0;
 390
 391    *((vu_long *)dest) = data;
 392
 393    /* re-enable interrupts if necessary */
 394    if (flag)
 395      enable_interrupts();
 396
 397    /* data polling for D7 */
 398    start = get_timer (0);
 399    while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
 400        if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 401            return (1);
 402        }
 403    }
 404    return (0);
 405}
 406
 407/*-----------------------------------------------------------------------
 408 */
 409