uboot/board/evb64260/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 Hymod board by Murray.Jensen@cmst.csiro.au, 20-Oct-00
  24 */
  25
  26#include <common.h>
  27#include <mpc8xx.h>
  28#include <galileo/gt64260R.h>
  29#include <galileo/memory.h>
  30#include "intel_flash.h"
  31
  32
  33/*-----------------------------------------------------------------------
  34 * Protection Flags:
  35 */
  36#define FLAG_PROTECT_SET        0x01
  37#define FLAG_PROTECT_CLEAR      0x02
  38
  39static void
  40bank_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
  58bank_erase_init(flash_info_t *info, int sect)
  59{
  60        bank_addr_t addrw, saddrw, eaddrw;
  61        int flag;
  62
  63#ifdef FLASH_DEBUG
  64        printf("0x%08x BANK_CMD_PROG\n", BANK_CMD_PROG);
  65        printf("0x%08x BANK_CMD_ERASE1\n", BANK_CMD_ERASE1);
  66        printf("0x%08x BANK_CMD_ERASE2\n", BANK_CMD_ERASE2);
  67        printf("0x%08x BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT);
  68        printf("0x%08x BANK_CMD_RST\n", BANK_CMD_RST);
  69        printf("0x%08x BANK_STAT_RDY\n", BANK_STAT_RDY);
  70        printf("0x%08x BANK_STAT_ERR\n", BANK_STAT_ERR);
  71#endif
  72
  73        saddrw = (bank_addr_t)info->start[sect];
  74        eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
  75
  76#ifdef FLASH_DEBUG
  77        printf("erasing sector %d, start addr = 0x%08lx "
  78                "(bank next word addr = 0x%08lx)\n", sect,
  79                (unsigned long)saddrw, (unsigned long)eaddrw);
  80#endif
  81
  82        /* Disable intrs which might cause a timeout here */
  83        flag = disable_interrupts();
  84
  85        for (addrw = saddrw; addrw < eaddrw; addrw++) {
  86#ifdef FLASH_DEBUG
  87                printf("  writing erase cmd to addr 0x%08lx\n",
  88                        (unsigned long)addrw);
  89#endif
  90                *addrw = BANK_CMD_ERASE1;
  91                *addrw = BANK_CMD_ERASE2;
  92        }
  93
  94        /* re-enable interrupts if necessary */
  95        if (flag)
  96                enable_interrupts();
  97}
  98
  99static int
 100bank_erase_poll(flash_info_t *info, int sect)
 101{
 102        bank_addr_t addrw, saddrw, eaddrw;
 103        int sectdone, haderr;
 104
 105        saddrw = (bank_addr_t)info->start[sect];
 106        eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
 107
 108        sectdone = 1;
 109        haderr = 0;
 110
 111        for (addrw = saddrw; addrw < eaddrw; addrw++) {
 112                bank_word_t stat = *addrw;
 113
 114#ifdef FLASH_DEBUG
 115                printf("  checking status at addr "
 116                        "0x%08x [0x%08x]\n",
 117                        (unsigned long)addrw, stat);
 118#endif
 119                if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY)
 120                        sectdone = 0;
 121                else if ((stat & BANK_STAT_ERR) != 0) {
 122                        printf(" failed on sector %d "
 123                                "(stat = 0x%08x) at "
 124                                "address 0x%p\n",
 125                                sect, stat, addrw);
 126                        *addrw = BANK_CMD_CLR_STAT;
 127                        haderr = 1;
 128                }
 129        }
 130
 131        if (haderr)
 132                return (-1);
 133        else
 134                return (sectdone);
 135}
 136
 137int
 138write_word_intel(bank_addr_t addr, bank_word_t value)
 139{
 140        bank_word_t stat;
 141        ulong start;
 142        int flag, retval;
 143
 144        /* Disable interrupts which might cause a timeout here */
 145        flag = disable_interrupts();
 146
 147        *addr = BANK_CMD_PROG;
 148
 149        *addr = value;
 150
 151        /* re-enable interrupts if necessary */
 152        if (flag)
 153                enable_interrupts();
 154
 155        retval = 0;
 156
 157        /* data polling for D7 */
 158        start = get_timer (0);
 159        do {
 160                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 161                        retval = 1;
 162                        goto done;
 163                }
 164                stat = *addr;
 165        } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);
 166
 167        if ((stat & BANK_STAT_ERR) != 0) {
 168                printf("flash program failed (stat = 0x%08lx) "
 169                        "at address 0x%08lx\n", (ulong)stat, (ulong)addr);
 170                *addr = BANK_CMD_CLR_STAT;
 171                retval = 3;
 172        }
 173
 174done:
 175        /* reset to read mode */
 176        *addr = BANK_CMD_RST;
 177
 178        return (retval);
 179}
 180
 181/*-----------------------------------------------------------------------
 182 */
 183
 184int
 185flash_erase_intel(flash_info_t *info, int s_first, int s_last)
 186{
 187        int prot, sect, haderr;
 188        ulong start, now, last;
 189
 190#ifdef FLASH_DEBUG
 191        printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
 192                "  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
 193                (info - flash_info) + 1);
 194        flash_print_info(info);
 195#endif
 196
 197        if ((s_first < 0) || (s_first > s_last)) {
 198                if (info->flash_id == FLASH_UNKNOWN) {
 199                        printf ("- missing\n");
 200                } else {
 201                        printf ("- no sectors to erase\n");
 202                }
 203                return 1;
 204        }
 205
 206        prot = 0;
 207        for (sect=s_first; sect<=s_last; ++sect) {
 208                if (info->protect[sect]) {
 209                        prot++;
 210                }
 211        }
 212
 213        if (prot) {
 214                printf("- Warning: %d protected sector%s will not be erased!\n",
 215                        prot, (prot > 1 ? "s" : ""));
 216        }
 217
 218        start = get_timer (0);
 219        last = 0;
 220        haderr = 0;
 221
 222        for (sect = s_first; sect <= s_last; sect++) {
 223                if (info->protect[sect] == 0) { /* not protected */
 224                        ulong estart;
 225                        int sectdone;
 226
 227                        bank_erase_init(info, sect);
 228
 229                        /* wait at least 80us - let's wait 1 ms */
 230                        udelay (1000);
 231
 232                        estart = get_timer(start);
 233
 234                        do {
 235                                now = get_timer(start);
 236
 237                                if (now - estart > CONFIG_SYS_FLASH_ERASE_TOUT) {
 238                                        printf ("Timeout (sect %d)\n", sect);
 239                                        haderr = 1;
 240                                        break;
 241                                }
 242
 243#ifndef FLASH_DEBUG
 244                                /* show that we're waiting */
 245                                if ((now - last) > 1000) { /* every second */
 246                                        putc ('.');
 247                                        last = now;
 248                                }
 249#endif
 250
 251                                sectdone = bank_erase_poll(info, sect);
 252
 253                                if (sectdone < 0) {
 254                                        haderr = 1;
 255                                        break;
 256                                }
 257
 258                        } while (!sectdone);
 259
 260                        if (haderr)
 261                                break;
 262                }
 263        }
 264
 265        if (haderr > 0)
 266                printf (" failed\n");
 267        else
 268                printf (" done\n");
 269
 270        /* reset to read mode */
 271        for (sect = s_first; sect <= s_last; sect++) {
 272                if (info->protect[sect] == 0) { /* not protected */
 273                        bank_reset(info, sect);
 274                }
 275        }
 276        return haderr;
 277}
 278