uboot/board/mpl/vcma9/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   4 * Alex Zuepke <azu@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
  27ulong myflush (void);
  28
  29
  30#define FLASH_BANK_SIZE PHYS_FLASH_SIZE
  31#define MAIN_SECT_SIZE  0x10000 /* 64 KB */
  32
  33flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  34
  35
  36#define CMD_READ_ARRAY          0x000000F0
  37#define CMD_UNLOCK1             0x000000AA
  38#define CMD_UNLOCK2             0x00000055
  39#define CMD_ERASE_SETUP         0x00000080
  40#define CMD_ERASE_CONFIRM       0x00000030
  41#define CMD_PROGRAM             0x000000A0
  42#define CMD_UNLOCK_BYPASS       0x00000020
  43
  44#define MEM_FLASH_ADDR1         (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 1)))
  45#define MEM_FLASH_ADDR2         (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 1)))
  46
  47#define BIT_ERASE_DONE          0x00000080
  48#define BIT_RDY_MASK            0x00000080
  49#define BIT_PROGRAM_ERROR       0x00000020
  50#define BIT_TIMEOUT             0x80000000      /* our flag */
  51
  52#define READY 1
  53#define ERR   2
  54#define TMO   4
  55
  56/*-----------------------------------------------------------------------
  57 */
  58
  59ulong flash_init (void)
  60{
  61        int i, j;
  62        ulong size = 0;
  63
  64        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  65                ulong flashbase = 0;
  66
  67                flash_info[i].flash_id =
  68#if defined(CONFIG_AMD_LV400)
  69                        (AMD_MANUFACT & FLASH_VENDMASK) |
  70                        (AMD_ID_LV400B & FLASH_TYPEMASK);
  71#elif defined(CONFIG_AMD_LV800)
  72                        (AMD_MANUFACT & FLASH_VENDMASK) |
  73                        (AMD_ID_LV800B & FLASH_TYPEMASK);
  74#else
  75#error "Unknown flash configured"
  76#endif
  77                        flash_info[i].size = FLASH_BANK_SIZE;
  78                flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
  79                memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
  80                if (i == 0)
  81                        flashbase = PHYS_FLASH_1;
  82                else
  83                        panic ("configured too many flash banks!\n");
  84                for (j = 0; j < flash_info[i].sector_count; j++) {
  85                        if (j <= 3) {
  86                                /* 1st one is 16 KB */
  87                                if (j == 0) {
  88                                        flash_info[i].start[j] =
  89                                                flashbase + 0;
  90                                }
  91
  92                                /* 2nd and 3rd are both 8 KB */
  93                                if ((j == 1) || (j == 2)) {
  94                                        flash_info[i].start[j] =
  95                                                flashbase + 0x4000 + (j -
  96                                                                      1) *
  97                                                0x2000;
  98                                }
  99
 100                                /* 4th 32 KB */
 101                                if (j == 3) {
 102                                        flash_info[i].start[j] =
 103                                                flashbase + 0x8000;
 104                                }
 105                        } else {
 106                                flash_info[i].start[j] =
 107                                        flashbase + (j - 3) * MAIN_SECT_SIZE;
 108                        }
 109                }
 110                size += flash_info[i].size;
 111        }
 112
 113        flash_protect (FLAG_PROTECT_SET,
 114                       CONFIG_SYS_FLASH_BASE,
 115                       CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
 116                       &flash_info[0]);
 117
 118        flash_protect (FLAG_PROTECT_SET,
 119                       CONFIG_ENV_ADDR,
 120                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
 121
 122        return size;
 123}
 124
 125/*-----------------------------------------------------------------------
 126 */
 127void flash_print_info (flash_info_t * info)
 128{
 129        int i;
 130
 131        switch (info->flash_id & FLASH_VENDMASK) {
 132        case (AMD_MANUFACT & FLASH_VENDMASK):
 133                puts ("AMD: ");
 134                break;
 135        default:
 136                puts ("Unknown Vendor ");
 137                break;
 138        }
 139
 140        switch (info->flash_id & FLASH_TYPEMASK) {
 141        case (AMD_ID_LV400B & FLASH_TYPEMASK):
 142                puts ("1x Amd29LV400BB (4Mbit)\n");
 143                break;
 144        case (AMD_ID_LV800B & FLASH_TYPEMASK):
 145                puts ("1x Amd29LV800BB (8Mbit)\n");
 146                break;
 147        default:
 148                puts ("Unknown Chip Type\n");
 149                goto Done;
 150                break;
 151        }
 152
 153        printf ("  Size: %ld MB in %d Sectors\n",
 154                info->size >> 20, info->sector_count);
 155
 156        puts ("  Sector Start Addresses:");
 157        for (i = 0; i < info->sector_count; i++) {
 158                if ((i % 5) == 0) {
 159                        puts ("\n   ");
 160                }
 161                printf (" %08lX%s", info->start[i],
 162                        info->protect[i] ? " (RO)" : "     ");
 163        }
 164        puts ("\n");
 165
 166Done:   ;
 167}
 168
 169/*-----------------------------------------------------------------------
 170 */
 171
 172int flash_erase (flash_info_t * info, int s_first, int s_last)
 173{
 174        ushort result;
 175        int iflag, cflag, prot, sect;
 176        int rc = ERR_OK;
 177        int chip;
 178
 179        /* first look for protection bits */
 180
 181        if (info->flash_id == FLASH_UNKNOWN)
 182                return ERR_UNKNOWN_FLASH_TYPE;
 183
 184        if ((s_first < 0) || (s_first > s_last)) {
 185                return ERR_INVAL;
 186        }
 187
 188        if ((info->flash_id & FLASH_VENDMASK) !=
 189            (AMD_MANUFACT & FLASH_VENDMASK)) {
 190                return ERR_UNKNOWN_FLASH_VENDOR;
 191        }
 192
 193        prot = 0;
 194        for (sect = s_first; sect <= s_last; ++sect) {
 195                if (info->protect[sect]) {
 196                        prot++;
 197                }
 198        }
 199        if (prot)
 200                return ERR_PROTECTED;
 201
 202        /*
 203         * Disable interrupts which might cause a timeout
 204         * here. Remember that our exception vectors are
 205         * at address 0 in the flash, and we don't want a
 206         * (ticker) exception to happen while the flash
 207         * chip is in programming mode.
 208         */
 209        cflag = icache_status ();
 210        icache_disable ();
 211        iflag = disable_interrupts ();
 212
 213        /* Start erase on unprotected sectors */
 214        for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
 215                printf ("Erasing sector %2d ... ", sect);
 216
 217                /* arm simple, non interrupt dependent timer */
 218                reset_timer_masked ();
 219
 220                if (info->protect[sect] == 0) { /* not protected */
 221                        vu_short *addr = (vu_short *) (info->start[sect]);
 222
 223                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 224                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 225                        MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
 226
 227                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 228                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 229                        *addr = CMD_ERASE_CONFIRM;
 230
 231                        /* wait until flash is ready */
 232                        chip = 0;
 233
 234                        do {
 235                                result = *addr;
 236
 237                                /* check timeout */
 238                                if (get_timer_masked () >
 239                                    CONFIG_SYS_FLASH_ERASE_TOUT) {
 240                                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
 241                                        chip = TMO;
 242                                        break;
 243                                }
 244
 245                                if (!chip
 246                                    && (result & 0xFFFF) & BIT_ERASE_DONE)
 247                                        chip = READY;
 248
 249                                if (!chip
 250                                    && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
 251                                        chip = ERR;
 252
 253                        } while (!chip);
 254
 255                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
 256
 257                        if (chip == ERR) {
 258                                rc = ERR_PROG_ERROR;
 259                                goto outahere;
 260                        }
 261                        if (chip == TMO) {
 262                                rc = ERR_TIMOUT;
 263                                goto outahere;
 264                        }
 265
 266                        puts ("ok.\n");
 267                } else {        /* it was protected */
 268
 269                        puts ("protected!\n");
 270                }
 271        }
 272
 273        if (ctrlc ())
 274                puts ("User Interrupt!\n");
 275
 276      outahere:
 277        /* allow flash to settle - wait 10 ms */
 278        udelay_masked (10000);
 279
 280        if (iflag)
 281                enable_interrupts ();
 282
 283        if (cflag)
 284                icache_enable ();
 285
 286        return rc;
 287}
 288
 289/*-----------------------------------------------------------------------
 290 * Copy memory to flash
 291 */
 292
 293static int write_hword (flash_info_t * info, ulong dest, ushort data)
 294{
 295        vu_short *addr = (vu_short *) dest;
 296        ushort result;
 297        int rc = ERR_OK;
 298        int cflag, iflag;
 299        int chip;
 300
 301        /*
 302         * Check if Flash is (sufficiently) erased
 303         */
 304        result = *addr;
 305        if ((result & data) != data)
 306                return ERR_NOT_ERASED;
 307
 308
 309        /*
 310         * Disable interrupts which might cause a timeout
 311         * here. Remember that our exception vectors are
 312         * at address 0 in the flash, and we don't want a
 313         * (ticker) exception to happen while the flash
 314         * chip is in programming mode.
 315         */
 316        cflag = icache_status ();
 317        icache_disable ();
 318        iflag = disable_interrupts ();
 319
 320        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 321        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 322        MEM_FLASH_ADDR1 = CMD_PROGRAM;
 323        *addr = data;
 324
 325        /* arm simple, non interrupt dependent timer */
 326        reset_timer_masked ();
 327
 328        /* wait until flash is ready */
 329        chip = 0;
 330        do {
 331                result = *addr;
 332
 333                /* check timeout */
 334                if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) {
 335                        chip = ERR | TMO;
 336                        break;
 337                }
 338                if (!chip && ((result & 0x80) == (data & 0x80)))
 339                        chip = READY;
 340
 341                if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
 342                        result = *addr;
 343
 344                        if ((result & 0x80) == (data & 0x80))
 345                                chip = READY;
 346                        else
 347                                chip = ERR;
 348                }
 349
 350        } while (!chip);
 351
 352        *addr = CMD_READ_ARRAY;
 353
 354        if (chip == ERR || *addr != data)
 355                rc = ERR_PROG_ERROR;
 356
 357        if (iflag)
 358                enable_interrupts ();
 359
 360        if (cflag)
 361                icache_enable ();
 362
 363        return rc;
 364}
 365
 366/*-----------------------------------------------------------------------
 367 * Copy memory to flash.
 368 */
 369
 370int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 371{
 372        ulong cp, wp;
 373        int l;
 374        int i, rc;
 375        ushort data;
 376
 377        wp = (addr & ~1);       /* get lower word aligned address */
 378
 379        /*
 380         * handle unaligned start bytes
 381         */
 382        if ((l = addr - wp) != 0) {
 383                data = 0;
 384                for (i = 0, cp = wp; i < l; ++i, ++cp) {
 385                        data = (data >> 8) | (*(uchar *) cp << 8);
 386                }
 387                for (; i < 2 && cnt > 0; ++i) {
 388                        data = (data >> 8) | (*src++ << 8);
 389                        --cnt;
 390                        ++cp;
 391                }
 392                for (; cnt == 0 && i < 2; ++i, ++cp) {
 393                        data = (data >> 8) | (*(uchar *) cp << 8);
 394                }
 395
 396                if ((rc = write_hword (info, wp, data)) != 0) {
 397                        return (rc);
 398                }
 399                wp += 2;
 400        }
 401
 402        /*
 403         * handle word aligned part
 404         */
 405        while (cnt >= 2) {
 406                data = *((vu_short *) src);
 407                if ((rc = write_hword (info, wp, data)) != 0) {
 408                        return (rc);
 409                }
 410                src += 2;
 411                wp += 2;
 412                cnt -= 2;
 413        }
 414
 415        if (cnt == 0) {
 416                return ERR_OK;
 417        }
 418
 419        /*
 420         * handle unaligned tail bytes
 421         */
 422        data = 0;
 423        for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
 424                data = (data >> 8) | (*src++ << 8);
 425                --cnt;
 426        }
 427        for (; i < 2; ++i, ++cp) {
 428                data = (data >> 8) | (*(uchar *) cp << 8);
 429        }
 430
 431        return write_hword (info, wp, data);
 432}
 433