uboot/board/Marvell/common/intel_flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 *
  23 * Hacked for the marvell db64360 eval board by
  24 * Ingo Assmus <ingo.assmus@keymile.com>
  25 */
  26
  27#include <common.h>
  28#include <mpc8xx.h>
  29#include "../include/mv_gen_reg.h"
  30#include "../include/memory.h"
  31#include "intel_flash.h"
  32
  33
  34/*-----------------------------------------------------------------------
  35 * Protection Flags:
  36 */
  37#define FLAG_PROTECT_SET        0x01
  38#define FLAG_PROTECT_CLEAR      0x02
  39
  40static void bank_reset (flash_info_t * info, int sect)
  41{
  42        bank_addr_t addrw, eaddrw;
  43
  44        addrw = (bank_addr_t) info->start[sect];
  45        eaddrw = BANK_ADDR_NEXT_WORD (addrw);
  46
  47        while (addrw < eaddrw) {
  48#ifdef FLASH_DEBUG
  49                printf ("  writing reset cmd to addr 0x%08lx\n",
  50                        (unsigned long) addrw);
  51#endif
  52                *addrw = BANK_CMD_RST;
  53                addrw++;
  54        }
  55}
  56
  57static void bank_erase_init (flash_info_t * info, int sect)
  58{
  59        bank_addr_t addrw, saddrw, eaddrw;
  60        int flag;
  61
  62#ifdef FLASH_DEBUG
  63        printf ("0x%08x BANK_CMD_PROG\n", BANK_CMD_PROG);
  64        printf ("0x%08x BANK_CMD_ERASE1\n", BANK_CMD_ERASE1);
  65        printf ("0x%08x BANK_CMD_ERASE2\n", BANK_CMD_ERASE2);
  66        printf ("0x%08x BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT);
  67        printf ("0x%08x BANK_CMD_RST\n", BANK_CMD_RST);
  68        printf ("0x%08x BANK_STAT_RDY\n", BANK_STAT_RDY);
  69        printf ("0x%08x BANK_STAT_ERR\n", BANK_STAT_ERR);
  70#endif
  71
  72        saddrw = (bank_addr_t) info->start[sect];
  73        eaddrw = BANK_ADDR_NEXT_WORD (saddrw);
  74
  75#ifdef FLASH_DEBUG
  76        printf ("erasing sector %d, start addr = 0x%08lx "
  77                "(bank next word addr = 0x%08lx)\n", sect,
  78                (unsigned long) saddrw, (unsigned long) eaddrw);
  79#endif
  80
  81        /* Disable intrs which might cause a timeout here */
  82        flag = disable_interrupts ();
  83
  84        for (addrw = saddrw; addrw < eaddrw; addrw++) {
  85#ifdef FLASH_DEBUG
  86                printf ("  writing erase cmd to addr 0x%08lx\n",
  87                        (unsigned long) addrw);
  88#endif
  89                *addrw = BANK_CMD_ERASE1;
  90                *addrw = BANK_CMD_ERASE2;
  91        }
  92
  93        /* re-enable interrupts if necessary */
  94        if (flag)
  95                enable_interrupts ();
  96}
  97
  98static int bank_erase_poll (flash_info_t * info, int sect)
  99{
 100        bank_addr_t addrw, saddrw, eaddrw;
 101        int sectdone, haderr;
 102
 103        saddrw = (bank_addr_t) info->start[sect];
 104        eaddrw = BANK_ADDR_NEXT_WORD (saddrw);
 105
 106        sectdone = 1;
 107        haderr = 0;
 108
 109        for (addrw = saddrw; addrw < eaddrw; addrw++) {
 110                bank_word_t stat = *addrw;
 111
 112#ifdef FLASH_DEBUG
 113                printf ("  checking status at addr "
 114                        "0x%08x [0x%08x]\n", (unsigned long) addrw, stat);
 115#endif
 116                if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY)
 117                        sectdone = 0;
 118                else if ((stat & BANK_STAT_ERR) != 0) {
 119                        printf (" failed on sector %d "
 120                                "(stat = 0x%08x) at "
 121                                "address 0x%p\n", sect, stat, addrw);
 122                        *addrw = BANK_CMD_CLR_STAT;
 123                        haderr = 1;
 124                }
 125        }
 126
 127        if (haderr)
 128                return (-1);
 129        else
 130                return (sectdone);
 131}
 132
 133int write_word_intel (bank_addr_t addr, bank_word_t value)
 134{
 135        bank_word_t stat;
 136        ulong start;
 137        int flag, retval;
 138
 139        /* Disable interrupts which might cause a timeout here */
 140        flag = disable_interrupts ();
 141
 142        *addr = BANK_CMD_PROG;
 143
 144        *addr = value;
 145
 146        /* re-enable interrupts if necessary */
 147        if (flag)
 148                enable_interrupts ();
 149
 150        retval = 0;
 151
 152        /* data polling for D7 */
 153        start = get_timer (0);
 154        do {
 155                if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 156                        retval = 1;
 157                        goto done;
 158                }
 159                stat = *addr;
 160        } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);
 161
 162        if ((stat & BANK_STAT_ERR) != 0) {
 163                printf ("flash program failed (stat = 0x%08lx) "
 164                        "at address 0x%08lx\n", (ulong) stat, (ulong) addr);
 165                *addr = BANK_CMD_CLR_STAT;
 166                retval = 3;
 167        }
 168
 169      done:
 170        /* reset to read mode */
 171        *addr = BANK_CMD_RST;
 172
 173        return (retval);
 174}
 175
 176/*-----------------------------------------------------------------------
 177 */
 178
 179int flash_erase_intel (flash_info_t * info, int s_first, int s_last)
 180{
 181        int prot, sect, haderr;
 182        ulong start, now, last;
 183
 184#ifdef FLASH_DEBUG
 185        printf ("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
 186                "  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
 187                (info - flash_info) + 1);
 188        flash_print_info (info);
 189#endif
 190
 191        if ((s_first < 0) || (s_first > s_last)) {
 192                if (info->flash_id == FLASH_UNKNOWN) {
 193                        printf ("- missing\n");
 194                } else {
 195                        printf ("- no sectors to erase\n");
 196                }
 197                return 1;
 198        }
 199
 200        prot = 0;
 201        for (sect = s_first; sect <= s_last; ++sect) {
 202                if (info->protect[sect]) {
 203                        prot++;
 204                }
 205        }
 206
 207        if (prot) {
 208                printf ("- Warning: %d protected sector%s will not be erased!\n", prot, (prot > 1 ? "s" : ""));
 209        }
 210
 211        start = get_timer (0);
 212        last = 0;
 213        haderr = 0;
 214
 215        for (sect = s_first; sect <= s_last; sect++) {
 216                if (info->protect[sect] == 0) { /* not protected */
 217                        ulong estart;
 218                        int sectdone;
 219
 220                        bank_erase_init (info, sect);
 221
 222                        /* wait at least 80us - let's wait 1 ms */
 223                        udelay (1000);
 224
 225                        estart = get_timer (start);
 226
 227                        do {
 228                                now = get_timer (start);
 229
 230                                if (now - estart > CONFIG_SYS_FLASH_ERASE_TOUT) {
 231                                        printf ("Timeout (sect %d)\n", sect);
 232                                        haderr = 1;
 233                                        break;
 234                                }
 235#ifndef FLASH_DEBUG
 236                                /* show that we're waiting */
 237                                if ((now - last) > 1000) {      /* every second */
 238                                        putc ('.');
 239                                        last = now;
 240                                }
 241#endif
 242
 243                                sectdone = bank_erase_poll (info, sect);
 244
 245                                if (sectdone < 0) {
 246                                        haderr = 1;
 247                                        break;
 248                                }
 249
 250                        } while (!sectdone);
 251
 252                        if (haderr)
 253                                break;
 254                }
 255        }
 256
 257        if (haderr > 0)
 258                printf (" failed\n");
 259        else
 260                printf (" done\n");
 261
 262        /* reset to read mode */
 263        for (sect = s_first; sect <= s_last; sect++) {
 264                if (info->protect[sect] == 0) { /* not protected */
 265                        bank_reset (info, sect);
 266                }
 267        }
 268        return haderr;
 269}
 270