uboot/board/smdk2410/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                printf ("AMD: ");
 134                break;
 135        default:
 136                printf ("Unknown Vendor ");
 137                break;
 138        }
 139
 140        switch (info->flash_id & FLASH_TYPEMASK) {
 141        case (AMD_ID_LV400B & FLASH_TYPEMASK):
 142                printf ("1x Amd29LV400BB (4Mbit)\n");
 143                break;
 144        case (AMD_ID_LV800B & FLASH_TYPEMASK):
 145                printf ("1x Amd29LV800BB (8Mbit)\n");
 146                break;
 147        default:
 148                printf ("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        printf ("  Sector Start Addresses:");
 157        for (i = 0; i < info->sector_count; i++) {
 158                if ((i % 5) == 0) {
 159                        printf ("\n   ");
 160                }
 161                printf (" %08lX%s", info->start[i],
 162                        info->protect[i] ? " (RO)" : "     ");
 163        }
 164        printf ("\n");
 165
 166      Done:;
 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                        printf ("ok.\n");
 267                } else {        /* it was protected */
 268
 269                        printf ("protected!\n");
 270                }
 271        }
 272
 273        if (ctrlc ())
 274                printf ("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_UNLOCK_BYPASS;
 323        *addr = CMD_PROGRAM;
 324        *addr = data;
 325
 326        /* arm simple, non interrupt dependent timer */
 327        reset_timer_masked ();
 328
 329        /* wait until flash is ready */
 330        chip = 0;
 331        do {
 332                result = *addr;
 333
 334                /* check timeout */
 335                if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) {
 336                        chip = ERR | TMO;
 337                        break;
 338                }
 339                if (!chip && ((result & 0x80) == (data & 0x80)))
 340                        chip = READY;
 341
 342                if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
 343                        result = *addr;
 344
 345                        if ((result & 0x80) == (data & 0x80))
 346                                chip = READY;
 347                        else
 348                                chip = ERR;
 349                }
 350
 351        } while (!chip);
 352
 353        *addr = CMD_READ_ARRAY;
 354
 355        if (chip == ERR || *addr != data)
 356                rc = ERR_PROG_ERROR;
 357
 358        if (iflag)
 359                enable_interrupts ();
 360
 361        if (cflag)
 362                icache_enable ();
 363
 364        return rc;
 365}
 366
 367/*-----------------------------------------------------------------------
 368 * Copy memory to flash.
 369 */
 370
 371int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 372{
 373        ulong cp, wp;
 374        int l;
 375        int i, rc;
 376        ushort data;
 377
 378        wp = (addr & ~1);       /* get lower word aligned address */
 379
 380        /*
 381         * handle unaligned start bytes
 382         */
 383        if ((l = addr - wp) != 0) {
 384                data = 0;
 385                for (i = 0, cp = wp; i < l; ++i, ++cp) {
 386                        data = (data >> 8) | (*(uchar *) cp << 8);
 387                }
 388                for (; i < 2 && cnt > 0; ++i) {
 389                        data = (data >> 8) | (*src++ << 8);
 390                        --cnt;
 391                        ++cp;
 392                }
 393                for (; cnt == 0 && i < 2; ++i, ++cp) {
 394                        data = (data >> 8) | (*(uchar *) cp << 8);
 395                }
 396
 397                if ((rc = write_hword (info, wp, data)) != 0) {
 398                        return (rc);
 399                }
 400                wp += 2;
 401        }
 402
 403        /*
 404         * handle word aligned part
 405         */
 406        while (cnt >= 2) {
 407                data = *((vu_short *) src);
 408                if ((rc = write_hword (info, wp, data)) != 0) {
 409                        return (rc);
 410                }
 411                src += 2;
 412                wp += 2;
 413                cnt -= 2;
 414        }
 415
 416        if (cnt == 0) {
 417                return ERR_OK;
 418        }
 419
 420        /*
 421         * handle unaligned tail bytes
 422         */
 423        data = 0;
 424        for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
 425                data = (data >> 8) | (*src++ << 8);
 426                --cnt;
 427        }
 428        for (; i < 2; ++i, ++cp) {
 429                data = (data >> 8) | (*(uchar *) cp << 8);
 430        }
 431
 432        return write_hword (info, wp, data);
 433}
 434