uboot/board/ep7312/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   4 * Marius Groeger <mgroeger@sysgo.de>
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 */
  24
  25#include <common.h>
  26
  27#define FLASH_BANK_SIZE 0x1000000
  28#define MAIN_SECT_SIZE  0x20000
  29
  30flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  31
  32
  33/*-----------------------------------------------------------------------
  34 */
  35
  36ulong flash_init (void)
  37{
  38        int i, j;
  39        ulong size = 0;
  40
  41        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  42                ulong flashbase = 0;
  43
  44                flash_info[i].flash_id =
  45                                (INTEL_MANUFACT & FLASH_VENDMASK) |
  46                                (INTEL_ID_28F128J3 & FLASH_TYPEMASK);
  47                flash_info[i].size = FLASH_BANK_SIZE;
  48                flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
  49                memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
  50                if (i == 0)
  51                        flashbase = PHYS_FLASH_1;
  52                else
  53                        panic ("configured too many flash banks!\n");
  54                for (j = 0; j < flash_info[i].sector_count; j++) {
  55                        flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE;
  56                }
  57                size += flash_info[i].size;
  58        }
  59
  60        /* Protect monitor and environment sectors
  61         */
  62        flash_protect ( FLAG_PROTECT_SET,
  63                        CONFIG_SYS_FLASH_BASE,
  64                        CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
  65                        &flash_info[0]);
  66
  67        flash_protect ( FLAG_PROTECT_SET,
  68                        CONFIG_ENV_ADDR,
  69                        CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
  70
  71        return size;
  72}
  73
  74/*-----------------------------------------------------------------------
  75 */
  76void flash_print_info (flash_info_t * info)
  77{
  78        int i;
  79
  80        switch (info->flash_id & FLASH_VENDMASK) {
  81        case (INTEL_MANUFACT & FLASH_VENDMASK):
  82                printf ("Intel: ");
  83                break;
  84        default:
  85                printf ("Unknown Vendor ");
  86                break;
  87        }
  88
  89        switch (info->flash_id & FLASH_TYPEMASK) {
  90        case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
  91                printf ("28F128J3 (128Mbit)\n");
  92                break;
  93        default:
  94                printf ("Unknown Chip Type\n");
  95                goto Done;
  96                break;
  97        }
  98
  99        printf ("  Size: %ld MB in %d Sectors\n",
 100                        info->size >> 20, info->sector_count);
 101
 102        printf ("  Sector Start Addresses:");
 103        for (i = 0; i < info->sector_count; i++) {
 104                if ((i % 5) == 0) {
 105                        printf ("\n   ");
 106                }
 107                printf (" %08lX%s", info->start[i],
 108                                info->protect[i] ? " (RO)" : "     ");
 109        }
 110        printf ("\n");
 111
 112Done:   ;
 113}
 114
 115/*-----------------------------------------------------------------------
 116 */
 117
 118int flash_erase (flash_info_t * info, int s_first, int s_last)
 119{
 120        int flag, prot, sect;
 121        int rc = ERR_OK;
 122
 123        if (info->flash_id == FLASH_UNKNOWN)
 124                return ERR_UNKNOWN_FLASH_TYPE;
 125
 126        if ((s_first < 0) || (s_first > s_last)) {
 127                return ERR_INVAL;
 128        }
 129
 130        if ((info->flash_id & FLASH_VENDMASK) !=
 131                (INTEL_MANUFACT & FLASH_VENDMASK)) {
 132                return ERR_UNKNOWN_FLASH_VENDOR;
 133        }
 134
 135        prot = 0;
 136        for (sect = s_first; sect <= s_last; ++sect) {
 137                if (info->protect[sect]) {
 138                        prot++;
 139                }
 140        }
 141        if (prot)
 142                return ERR_PROTECTED;
 143
 144        /*
 145         * Disable interrupts which might cause a timeout
 146         * here. Remember that our exception vectors are
 147         * at address 0 in the flash, and we don't want a
 148         * (ticker) exception to happen while the flash
 149         * chip is in programming mode.
 150         */
 151        flag = disable_interrupts ();
 152
 153        /* Start erase on unprotected sectors */
 154        for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
 155
 156                printf ("Erasing sector %2d ... ", sect);
 157
 158                /* arm simple, non interrupt dependent timer */
 159                reset_timer_masked ();
 160
 161                if (info->protect[sect] == 0) { /* not protected */
 162                        vu_short *addr = (vu_short *) (info->start[sect]);
 163
 164                        *addr = 0x20;           /* erase setup */
 165                        *addr = 0xD0;           /* erase confirm */
 166
 167                        while ((*addr & 0x80) != 0x80) {
 168                                if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) {
 169                                        *addr = 0xB0;   /* suspend erase */
 170                                        *addr = 0xFF;   /* reset to read mode */
 171                                        rc = ERR_TIMOUT;
 172                                        goto outahere;
 173                                }
 174                        }
 175
 176                        /* clear status register command */
 177                        *addr = 0x50;
 178                        /* reset to read mode */
 179                        *addr = 0xFF;
 180                }
 181                printf ("ok.\n");
 182        }
 183        if (ctrlc ())
 184                printf ("User Interrupt!\n");
 185
 186  outahere:
 187
 188        /* allow flash to settle - wait 10 ms */
 189        udelay_masked (10000);
 190
 191        if (flag)
 192                enable_interrupts ();
 193
 194        return rc;
 195}
 196
 197/*-----------------------------------------------------------------------
 198 * Copy memory to flash
 199 */
 200
 201static int write_word (flash_info_t * info, ulong dest, ushort data)
 202{
 203        vu_short *addr = (vu_short *) dest, val;
 204        int rc = ERR_OK;
 205        int flag;
 206
 207        /* Check if Flash is (sufficiently) erased
 208         */
 209        if ((*addr & data) != data)
 210                return ERR_NOT_ERASED;
 211
 212        /*
 213         * Disable interrupts which might cause a timeout
 214         * here. Remember that our exception vectors are
 215         * at address 0 in the flash, and we don't want a
 216         * (ticker) exception to happen while the flash
 217         * chip is in programming mode.
 218         */
 219        flag = disable_interrupts ();
 220
 221        /* clear status register command */
 222        *addr = 0x50;
 223
 224        /* program set-up command */
 225        *addr = 0x40;
 226
 227        /* latch address/data */
 228        *addr = data;
 229
 230        /* arm simple, non interrupt dependent timer */
 231        reset_timer_masked ();
 232
 233        /* wait while polling the status register */
 234        while (((val = *addr) & 0x80) != 0x80) {
 235                if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) {
 236                        rc = ERR_TIMOUT;
 237                        /* suspend program command */
 238                        *addr = 0xB0;
 239                        goto outahere;
 240                }
 241        }
 242
 243        if (val & 0x1A) {                       /* check for error */
 244                printf ("\nFlash write error %02x at address %08lx\n",
 245                                (int) val, (unsigned long) dest);
 246                if (val & (1 << 3)) {
 247                        printf ("Voltage range error.\n");
 248                        rc = ERR_PROG_ERROR;
 249                        goto outahere;
 250                }
 251                if (val & (1 << 1)) {
 252                        printf ("Device protect error.\n");
 253                        rc = ERR_PROTECTED;
 254                        goto outahere;
 255                }
 256                if (val & (1 << 4)) {
 257                        printf ("Programming error.\n");
 258                        rc = ERR_PROG_ERROR;
 259                        goto outahere;
 260                }
 261                rc = ERR_PROG_ERROR;
 262                goto outahere;
 263        }
 264
 265  outahere:
 266        /* read array command */
 267        *addr = 0xFF;
 268
 269        if (flag)
 270                enable_interrupts ();
 271
 272        return rc;
 273}
 274
 275/*-----------------------------------------------------------------------
 276 * Copy memory to flash.
 277 */
 278
 279int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 280{
 281        ulong cp, wp;
 282        ushort data;
 283        int l;
 284        int i, rc;
 285
 286        wp = (addr & ~1);                       /* get lower word aligned address */
 287
 288        /*
 289         * handle unaligned start bytes
 290         */
 291        if ((l = addr - wp) != 0) {
 292                data = 0;
 293                for (i = 0, cp = wp; i < l; ++i, ++cp) {
 294                        data = (data >> 8) | (*(uchar *) cp << 8);
 295                }
 296                for (; i < 2 && cnt > 0; ++i) {
 297                        data = (data >> 8) | (*src++ << 8);
 298                        --cnt;
 299                        ++cp;
 300                }
 301                for (; cnt == 0 && i < 2; ++i, ++cp) {
 302                        data = (data >> 8) | (*(uchar *) cp << 8);
 303                }
 304
 305                if ((rc = write_word (info, wp, data)) != 0) {
 306                        return (rc);
 307                }
 308                wp += 2;
 309        }
 310
 311        /*
 312         * handle word aligned part
 313         */
 314        while (cnt >= 2) {
 315                data = *((vu_short *) src);
 316                if ((rc = write_word (info, wp, data)) != 0) {
 317                        return (rc);
 318                }
 319                src += 2;
 320                wp += 2;
 321                cnt -= 2;
 322        }
 323
 324        if (cnt == 0) {
 325                return ERR_OK;
 326        }
 327
 328        /*
 329         * handle unaligned tail bytes
 330         */
 331        data = 0;
 332        for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
 333                data = (data >> 8) | (*src++ << 8);
 334                --cnt;
 335        }
 336        for (; i < 2; ++i, ++cp) {
 337                data = (data >> 8) | (*(uchar *) cp << 8);
 338        }
 339
 340        return write_word (info, wp, data);
 341}
 342