uboot/board/trab/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Gary Jennejohn, DENX Software Engineering, <gj@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
  24/* #define DEBUG */
  25
  26#include <common.h>
  27#include <environment.h>
  28
  29static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  30
  31flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  32
  33
  34#define CMD_READ_ARRAY          0x00F000F0
  35#define CMD_UNLOCK1             0x00AA00AA
  36#define CMD_UNLOCK2             0x00550055
  37#define CMD_ERASE_SETUP         0x00800080
  38#define CMD_ERASE_CONFIRM       0x00300030
  39#define CMD_PROGRAM             0x00A000A0
  40#define CMD_UNLOCK_BYPASS       0x00200020
  41#define CMD_READ_MANF_ID        0x00900090
  42#define CMD_UNLOCK_BYPASS_RES1  0x00900090
  43#define CMD_UNLOCK_BYPASS_RES2  0x00000000
  44
  45#define MEM_FLASH_ADDR          (*(volatile u32 *)CONFIG_SYS_FLASH_BASE)
  46#define MEM_FLASH_ADDR1         (*(volatile u32 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 2)))
  47#define MEM_FLASH_ADDR2         (*(volatile u32 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 2)))
  48
  49#define BIT_ERASE_DONE          0x00800080
  50#define BIT_RDY_MASK            0x00800080
  51#define BIT_PROGRAM_ERROR       0x00200020
  52#define BIT_TIMEOUT             0x80000000      /* our flag */
  53
  54#define READY 1
  55#define ERR   2
  56#define TMO   4
  57
  58/*-----------------------------------------------------------------------
  59 */
  60
  61ulong flash_init (void)
  62{
  63        int i, j;
  64        ulong size = 0;
  65
  66        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  67                ulong flashbase = 0;
  68                flash_info_t *info = &flash_info[i];
  69
  70                /* Init: no FLASHes known */
  71                info->flash_id = FLASH_UNKNOWN;
  72
  73                size += flash_get_size (CONFIG_SYS_FLASH_BASE, info);
  74
  75                if (i == 0)
  76                        flashbase = CONFIG_SYS_FLASH_BASE;
  77                else
  78                        panic ("configured too many flash banks!\n");
  79                for (j = 0; j < info->sector_count; j++) {
  80
  81                        info->protect[j] = 0;
  82                        info->start[j] = flashbase;
  83
  84                        switch (info->flash_id & FLASH_TYPEMASK) {
  85                        case (FLASH_AM320B & FLASH_TYPEMASK):
  86                        case (FLASH_MXLV320B & FLASH_TYPEMASK):
  87                                /* Boot sector type: 8 x 8 + N x 128 kB */
  88                                flashbase += (j < 8) ? 0x4000 : 0x20000;
  89                                break;
  90                        case (FLASH_AM640U & FLASH_TYPEMASK):
  91                                /* Uniform sector type: 128 kB */
  92                                flashbase += 0x20000;
  93                                break;
  94                        default:
  95                                printf ("## Bad flash chip type 0x%04lX\n",
  96                                        info->flash_id & FLASH_TYPEMASK);
  97                        }
  98                }
  99        }
 100
 101        /*
 102         * Protect monitor and environment sectors
 103         */
 104        flash_protect ( FLAG_PROTECT_SET,
 105                        CONFIG_SYS_FLASH_BASE,
 106                        CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
 107                        &flash_info[0]);
 108
 109        flash_protect ( FLAG_PROTECT_SET,
 110                        CONFIG_ENV_ADDR,
 111                        CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
 112
 113#ifdef CONFIG_ENV_ADDR_REDUND
 114        flash_protect ( FLAG_PROTECT_SET,
 115                        CONFIG_ENV_ADDR_REDUND,
 116                        CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SIZE_REDUND - 1,
 117                        &flash_info[0]);
 118#endif
 119
 120        return size;
 121}
 122
 123/*-----------------------------------------------------------------------
 124 */
 125void flash_print_info (flash_info_t * info)
 126{
 127        int i;
 128
 129        switch (info->flash_id & FLASH_VENDMASK) {
 130        case (FLASH_MAN_AMD & FLASH_VENDMASK):
 131                        printf ("AMD ");                break;
 132        case (FLASH_MAN_FUJ & FLASH_VENDMASK):
 133                        printf ("FUJITSU ");            break;
 134        case (FLASH_MAN_MX  & FLASH_VENDMASK):
 135                        printf ("MACRONIX ");           break;
 136        default:        printf ("Unknown Vendor ");     break;
 137        }
 138
 139        switch (info->flash_id & FLASH_TYPEMASK) {
 140        case (FLASH_AM320B & FLASH_TYPEMASK):
 141                printf ("2x Am29LV320DB (32Mbit)\n");
 142                break;
 143        case (FLASH_MXLV320B & FLASH_TYPEMASK):
 144                printf ("2x MX29LV320DB (32Mbit)\n");
 145                break;
 146        case (FLASH_AM640U & FLASH_TYPEMASK):
 147                printf ("2x Am29LV640D (64Mbit)\n");
 148                break;
 149        default:
 150                printf ("Unknown Chip Type\n");
 151                goto Done;
 152                break;
 153        }
 154
 155        printf ("  Size: %ld MB in %d Sectors\n",
 156                        info->size >> 20, info->sector_count);
 157
 158        printf ("  Sector Start Addresses:");
 159        for (i = 0; i < info->sector_count; i++) {
 160                if ((i % 5) == 0) {
 161                        printf ("\n   ");
 162                }
 163                printf (" %08lX%s",
 164                        info->start[i],
 165                        info->protect[i] ? " (RO)" : "     ");
 166        }
 167        printf ("\n");
 168
 169Done:   ;
 170}
 171
 172/*-----------------------------------------------------------------------
 173 */
 174
 175int flash_erase (flash_info_t * info, int s_first, int s_last)
 176{
 177        ulong result;
 178
 179#if 0
 180        int cflag;
 181#endif
 182        int iflag, prot, sect;
 183        int rc = ERR_OK;
 184        int chip1, chip2;
 185
 186        debug ("flash_erase: s_first %d  s_last %d\n", s_first, s_last);
 187
 188        /* first look for protection bits */
 189
 190        if (info->flash_id == FLASH_UNKNOWN)
 191                return ERR_UNKNOWN_FLASH_TYPE;
 192
 193        if ((s_first < 0) || (s_first > s_last)) {
 194                return ERR_INVAL;
 195        }
 196
 197        switch (info->flash_id & FLASH_VENDMASK) {
 198        case (FLASH_MAN_AMD & FLASH_VENDMASK):  break;  /* OK */
 199        case (FLASH_MAN_FUJ & FLASH_VENDMASK):  break;  /* OK */
 200        case (FLASH_MAN_MX  & FLASH_VENDMASK):  break;  /* OK */
 201        default:
 202                debug ("## flash_erase: unknown manufacturer\n");
 203                return (ERR_UNKNOWN_FLASH_VENDOR);
 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 sectors will not be erased!\n",
 215                        prot);
 216        } else {
 217                printf ("\n");
 218        }
 219
 220        /*
 221         * Disable interrupts which might cause a timeout
 222         * here. Remember that our exception vectors are
 223         * at address 0 in the flash, and we don't want a
 224         * (ticker) exception to happen while the flash
 225         * chip is in programming mode.
 226         */
 227#if 0
 228        cflag = icache_status ();
 229        icache_disable ();
 230#endif
 231        iflag = disable_interrupts ();
 232
 233        /* Start erase on unprotected sectors */
 234        for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
 235
 236                debug ("Erasing sector %2d @ %08lX... ",
 237                        sect, info->start[sect]);
 238
 239                /* arm simple, non interrupt dependent timer */
 240                reset_timer_masked ();
 241
 242                if (info->protect[sect] == 0) { /* not protected */
 243                        vu_long *addr = (vu_long *) (info->start[sect]);
 244
 245                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 246                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 247                        MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
 248
 249                        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 250                        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 251                        *addr = CMD_ERASE_CONFIRM;
 252
 253                        /* wait until flash is ready */
 254                        chip1 = chip2 = 0;
 255
 256                        do {
 257                                result = *addr;
 258
 259                                /* check timeout */
 260                                if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) {
 261                                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
 262                                        chip1 = TMO;
 263                                        break;
 264                                }
 265
 266                                if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
 267                                        chip1 = READY;
 268
 269                                if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
 270                                        chip1 = ERR;
 271
 272                                if (!chip2 && (result >> 16) & BIT_ERASE_DONE)
 273                                        chip2 = READY;
 274
 275                                if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR)
 276                                        chip2 = ERR;
 277
 278                        } while (!chip1 || !chip2);
 279
 280                        MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
 281
 282                        if (chip1 == ERR || chip2 == ERR) {
 283                                rc = ERR_PROG_ERROR;
 284                                printf ("Flash erase error\n");
 285                                goto outahere;
 286                        }
 287                        if (chip1 == TMO) {
 288                                rc = ERR_TIMOUT;
 289                                printf ("Flash erase timeout error\n");
 290                                goto outahere;
 291                        }
 292                }
 293        }
 294
 295outahere:
 296        /* allow flash to settle - wait 10 ms */
 297        udelay_masked (10000);
 298
 299        if (iflag)
 300                enable_interrupts ();
 301
 302#if 0
 303        if (cflag)
 304                icache_enable ();
 305#endif
 306        return rc;
 307}
 308
 309/*-----------------------------------------------------------------------
 310 * Copy memory to flash
 311 */
 312
 313static int write_word (flash_info_t * info, ulong dest, ulong data)
 314{
 315        vu_long *addr = (vu_long *) dest;
 316        ulong result;
 317        int rc = ERR_OK;
 318
 319#if 0
 320        int cflag;
 321#endif
 322        int iflag;
 323        int chip1, chip2;
 324
 325        /*
 326         * Check if Flash is (sufficiently) erased
 327         */
 328        result = *addr;
 329        if ((result & data) != data)
 330                return ERR_NOT_ERASED;
 331
 332        /*
 333         * Disable interrupts which might cause a timeout
 334         * here. Remember that our exception vectors are
 335         * at address 0 in the flash, and we don't want a
 336         * (ticker) exception to happen while the flash
 337         * chip is in programming mode.
 338         */
 339#if 0
 340        cflag = icache_status ();
 341        icache_disable ();
 342#endif
 343        iflag = disable_interrupts ();
 344
 345        MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 346        MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 347        MEM_FLASH_ADDR1 = CMD_PROGRAM;
 348        *addr = data;
 349
 350        /* arm simple, non interrupt dependent timer */
 351        reset_timer_masked ();
 352
 353        /* wait until flash is ready */
 354        chip1 = chip2 = 0;
 355        do {
 356                result = *addr;
 357
 358                /* check timeout */
 359                if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) {
 360                        chip1 = ERR | TMO;
 361                        break;
 362                }
 363                if (!chip1 && ((result & 0x80) == (data & 0x80)))
 364                        chip1 = READY;
 365
 366                if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
 367                        result = *addr;
 368
 369                        if ((result & 0x80) == (data & 0x80))
 370                                chip1 = READY;
 371                        else
 372                                chip1 = ERR;
 373                }
 374
 375                if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16))))
 376                        chip2 = READY;
 377
 378                if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR)) {
 379                        result = *addr;
 380
 381                        if ((result & (0x80 << 16)) == (data & (0x80 << 16)))
 382                                chip2 = READY;
 383                        else
 384                                chip2 = ERR;
 385                }
 386
 387        } while (!chip1 || !chip2);
 388
 389        *addr = CMD_READ_ARRAY;
 390
 391        if (chip1 == ERR || chip2 == ERR || *addr != data) {
 392                rc = ERR_PROG_ERROR;
 393                printf ("Flash program error\n");
 394                debug ("chip1: %#x, chip2: %#x, addr: %#lx *addr: %#lx, "
 395                       "data: %#lx\n",
 396                       chip1, chip2, addr, *addr, data);
 397        }
 398
 399        if (iflag)
 400                enable_interrupts ();
 401
 402#if 0
 403        if (cflag)
 404                icache_enable ();
 405#endif
 406
 407        return rc;
 408}
 409
 410/*-----------------------------------------------------------------------
 411 * Copy memory to flash.
 412 */
 413
 414int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 415{
 416        ulong cp, wp, data;
 417        int l;
 418        int i, rc;
 419
 420        wp = (addr & ~3);       /* get lower word aligned address */
 421
 422        /*
 423         * handle unaligned start bytes
 424         */
 425        if ((l = addr - wp) != 0) {
 426                data = 0;
 427                for (i = 0, cp = wp; i < l; ++i, ++cp) {
 428                        data = (data >> 8) | (*(uchar *) cp << 24);
 429                }
 430                for (; i < 4 && cnt > 0; ++i) {
 431                        data = (data >> 8) | (*src++ << 24);
 432                        --cnt;
 433                        ++cp;
 434                }
 435                for (; cnt == 0 && i < 4; ++i, ++cp) {
 436                        data = (data >> 8) | (*(uchar *) cp << 24);
 437                }
 438
 439                if ((rc = write_word (info, wp, data)) != 0) {
 440                        goto Done;
 441                }
 442                wp += 4;
 443        }
 444
 445        /*
 446         * handle word aligned part
 447         */
 448        while (cnt >= 4) {
 449                if (((ulong)src) & 0x3) {
 450                        for (i = 0; i < 4; i++) {
 451                                ((char *)&data)[i] = ((vu_char *)src)[i];
 452                        }
 453                }
 454                else {
 455                        data = *((vu_long *) src);
 456                }
 457
 458                if ((rc = write_word (info, wp, data)) != 0) {
 459                        goto Done;
 460                }
 461                src += 4;
 462                wp += 4;
 463                cnt -= 4;
 464        }
 465
 466        if (cnt == 0) {
 467                rc = ERR_OK;
 468                goto Done;
 469        }
 470
 471        /*
 472         * handle unaligned tail bytes
 473         */
 474        data = 0;
 475        for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
 476                data = (data >> 8) | (*src++ << 24);
 477                --cnt;
 478        }
 479        for (; i < 4; ++i, ++cp) {
 480                data = (data >> 8) | (*(uchar *) cp << 24);
 481        }
 482
 483        rc = write_word (info, wp, data);
 484
 485        Done:
 486
 487        return (rc);
 488}
 489
 490/*-----------------------------------------------------------------------
 491 */
 492
 493static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 494{
 495        ulong value;
 496
 497        /* Write auto select command sequence and read Manufacturer ID */
 498        addr[0x0555] = CMD_UNLOCK1;
 499        addr[0x02AA] = CMD_UNLOCK2;
 500        addr[0x0555] = CMD_READ_MANF_ID;
 501
 502        value = addr[0];
 503
 504        debug ("Manuf. ID @ 0x%08lx: 0x%08lx\n", (ulong)addr, value);
 505
 506        switch (value) {
 507        case AMD_MANUFACT:
 508                info->flash_id = FLASH_MAN_AMD;
 509                break;
 510        case FUJ_MANUFACT:
 511                info->flash_id = FLASH_MAN_FUJ;
 512                break;
 513        case MX_MANUFACT:
 514                info->flash_id = FLASH_MAN_MX;
 515                break;
 516        default:
 517                info->flash_id = FLASH_UNKNOWN;
 518                info->sector_count = 0;
 519                info->size = 0;
 520                addr[0] = CMD_READ_ARRAY;       /* restore read mode */
 521                debug ("## flash_init: unknown manufacturer\n");
 522                return (0);                     /* no or unknown flash  */
 523        }
 524
 525        value = addr[1];                        /* device ID            */
 526
 527        debug ("Device ID @ 0x%08lx: 0x%08lx\n", (ulong)(&addr[1]), value);
 528
 529        switch (value) {
 530        case AMD_ID_LV320B:
 531                info->flash_id += FLASH_AM320B;
 532                info->sector_count = 71;
 533                info->size = 0x00800000;
 534
 535                addr[0] = CMD_READ_ARRAY;       /* restore read mode */
 536                break;                          /* =>  8 MB             */
 537
 538        case AMD_ID_LV640U:
 539                info->flash_id += FLASH_AM640U;
 540                info->sector_count = 128;
 541                info->size = 0x01000000;
 542
 543                addr[0] = CMD_READ_ARRAY;       /* restore read mode */
 544                break;                          /* => 16 MB             */
 545
 546        case MX_ID_LV320B:
 547                info->flash_id += FLASH_MXLV320B;
 548                info->sector_count = 71;
 549                info->size = 0x00800000;
 550
 551                addr[0] = CMD_READ_ARRAY;       /* restore read mode */
 552                break;                          /* =>  8 MB             */
 553
 554        default:
 555                debug ("## flash_init: unknown flash chip\n");
 556                info->flash_id = FLASH_UNKNOWN;
 557                addr[0] = CMD_READ_ARRAY;       /* restore read mode */
 558                return (0);                     /* => no or unknown flash */
 559
 560        }
 561
 562        if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
 563                printf ("** ERROR: sector count %d > max (%d) **\n",
 564                        info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
 565                info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 566        }
 567
 568        return (info->size);
 569}
 570