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