uboot/board/evb4510/flash.c
<<
>>
Prefs
   1/*
   2 *
   3 * Copyright (c) 2004   Cucy Systems (http://www.cucy.com)
   4 * Curt Brune <curt@cucy.com>
   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#include <asm/hardware.h>
  27#include <flash.h>
  28
  29flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  30
  31typedef enum {
  32        FLASH_DEV_U9_512KB = 0,
  33        FLASH_DEV_U7_2MB = 1
  34} FLASH_DEV;
  35
  36#define FLASH_DQ7               (0x80)
  37#define FLASH_DQ5               (0x20)
  38
  39#define PROG_ADDR               (0xAAA)
  40#define SETUP_ADDR              (0xAAA)
  41#define ID_ADDR                 (0xAAA)
  42#define UNLOCK_ADDR1            (0xAAA)
  43#define UNLOCK_ADDR2            (0x555)
  44
  45#define UNLOCK_CMD1             (0xAA)
  46#define UNLOCK_CMD2             (0x55)
  47#define ERASE_SUSPEND_CMD       (0xB0)
  48#define ERASE_RESUME_CMD        (0x30)
  49#define RESET_CMD               (0xF0)
  50#define ID_CMD                  (0x90)
  51#define SELECT_CMD              (0x90)
  52#define CHIPERASE_CMD           (0x10)
  53#define BYPASS_CMD              (0x20)
  54#define SECERASE_CMD            (0x30)
  55#define PROG_CMD                (0xa0)
  56#define SETUP_CMD               (0x80)
  57
  58#if 0
  59#define WRITE_UNLOCK(addr) { \
  60        PUT__U8( addr + UNLOCK_ADDR1, UNLOCK_CMD1); \
  61        PUT__U8( addr + UNLOCK_ADDR2, UNLOCK_CMD2); \
  62}
  63
  64/* auto select command */
  65#define CMD_ID(addr) WRITE_UNLOCK(addr); { \
  66        PUT__U8( addr + ID_ADDR, ID_CMD); \
  67}
  68
  69#define CMD_RESET(addr) WRITE_UNLOCK(addr); { \
  70        PUT__U8( addr + ID_ADDR, RESET_CMD); \
  71}
  72
  73#define CMD_ERASE_SEC(base, addr) WRITE_UNLOCK(base); \
  74        PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
  75        WRITE_UNLOCK(base); \
  76        PUT__U8( addr, SECERASE_CMD);
  77
  78#define CMD_ERASE_CHIP(base) WRITE_UNLOCK(base); \
  79        PUT__U8( base + SETUP_ADDR, SETUP_CMD); \
  80        WRITE_UNLOCK(base); \
  81        PUT__U8( base + SETUP_ADDR, CHIPERASE_CMD);
  82
  83/* prepare for bypass programming */
  84#define CMD_UNLOCK_BYPASS(addr) WRITE_UNLOCK(addr); { \
  85        PUT__U8( addr + ID_ADDR, 0x20); \
  86}
  87
  88/* terminate bypass programming */
  89#define CMD_BYPASS_RESET(addr) { \
  90        PUT__U8(addr, 0x90); \
  91        PUT__U8(addr, 0x00); \
  92}
  93#endif
  94
  95inline static void FLASH_CMD_UNLOCK (FLASH_DEV dev, u32 base)
  96{
  97        switch (dev) {
  98        case FLASH_DEV_U7_2MB:
  99                PUT__U8 (base + 0xAAA, 0xAA);
 100                PUT__U8 (base + 0x555, 0x55);
 101                break;
 102        case FLASH_DEV_U9_512KB:
 103                PUT__U8 (base + 0x555, 0xAA);
 104                PUT__U8 (base + 0x2AA, 0x55);
 105                break;
 106        }
 107}
 108
 109inline static void FLASH_CMD_SELECT (FLASH_DEV dev, u32 base)
 110{
 111        switch (dev) {
 112        case FLASH_DEV_U7_2MB:
 113                FLASH_CMD_UNLOCK (dev, base);
 114                PUT__U8 (base + 0xAAA, SELECT_CMD);
 115                break;
 116        case FLASH_DEV_U9_512KB:
 117                FLASH_CMD_UNLOCK (dev, base);
 118                PUT__U8 (base + 0x555, SELECT_CMD);
 119                break;
 120        }
 121}
 122
 123inline static void FLASH_CMD_RESET (FLASH_DEV dev, u32 base)
 124{
 125        switch (dev) {
 126        case FLASH_DEV_U7_2MB:
 127                FLASH_CMD_UNLOCK (dev, base);
 128                PUT__U8 (base + 0xAAA, RESET_CMD);
 129                break;
 130        case FLASH_DEV_U9_512KB:
 131                FLASH_CMD_UNLOCK (dev, base);
 132                PUT__U8 (base + 0x555, RESET_CMD);
 133                break;
 134        }
 135}
 136
 137inline static void FLASH_CMD_ERASE_SEC (FLASH_DEV dev, u32 base, u32 addr)
 138{
 139        switch (dev) {
 140        case FLASH_DEV_U7_2MB:
 141                FLASH_CMD_UNLOCK (dev, base);
 142                PUT__U8 (base + 0xAAA, SETUP_CMD);
 143                FLASH_CMD_UNLOCK (dev, base);
 144                PUT__U8 (addr, SECERASE_CMD);
 145                break;
 146        case FLASH_DEV_U9_512KB:
 147                FLASH_CMD_UNLOCK (dev, base);
 148                PUT__U8 (base + 0x555, SETUP_CMD);
 149                FLASH_CMD_UNLOCK (dev, base);
 150                PUT__U8 (addr, SECERASE_CMD);
 151                break;
 152        }
 153}
 154
 155inline static void FLASH_CMD_ERASE_CHIP (FLASH_DEV dev, u32 base)
 156{
 157        switch (dev) {
 158        case FLASH_DEV_U7_2MB:
 159                FLASH_CMD_UNLOCK (dev, base);
 160                PUT__U8 (base + 0xAAA, SETUP_CMD);
 161                FLASH_CMD_UNLOCK (dev, base);
 162                PUT__U8 (base, CHIPERASE_CMD);
 163                break;
 164        case FLASH_DEV_U9_512KB:
 165                FLASH_CMD_UNLOCK (dev, base);
 166                PUT__U8 (base + 0x555, SETUP_CMD);
 167                FLASH_CMD_UNLOCK (dev, base);
 168                PUT__U8 (base, CHIPERASE_CMD);
 169                break;
 170        }
 171}
 172
 173inline static void FLASH_CMD_UNLOCK_BYPASS (FLASH_DEV dev, u32 base)
 174{
 175        switch (dev) {
 176        case FLASH_DEV_U7_2MB:
 177                FLASH_CMD_UNLOCK (dev, base);
 178                PUT__U8 (base + 0xAAA, BYPASS_CMD);
 179                break;
 180        case FLASH_DEV_U9_512KB:
 181                FLASH_CMD_UNLOCK (dev, base);
 182                PUT__U8 (base + 0x555, BYPASS_CMD);
 183                break;
 184        }
 185}
 186
 187inline static void FLASH_CMD_BYPASS_RESET (FLASH_DEV dev, u32 base)
 188{
 189        PUT__U8 (base, SELECT_CMD);
 190        PUT__U8 (base, 0x0);
 191}
 192
 193/* poll for flash command completion */
 194static u16 _flash_poll (FLASH_DEV dev, u32 addr, u16 data, ulong timeOut)
 195{
 196        u32 done = 0;
 197        ulong t0;
 198
 199        u16 error = 0;
 200        volatile u16 flashData;
 201
 202        data = data & 0xFF;
 203        t0 = get_timer (0);
 204        while (get_timer (t0) < timeOut) {
 205                /*      for( i = 0; i < POLL_LOOPS; i++) { */
 206                /*  Read the Data */
 207                flashData = GET__U8 (addr);
 208
 209                /*  FLASH_DQ7 = Data? */
 210                if ((flashData & FLASH_DQ7) == (data & FLASH_DQ7)) {
 211                        done = 1;
 212                        break;
 213                }
 214
 215                /*  Check Timeout (FLASH_DQ5==1) */
 216                if (flashData & FLASH_DQ5) {
 217                        /*  Read the Data */
 218                        flashData = GET__U8 (addr);
 219
 220                        /*  FLASH_DQ7 = Data? */
 221                        if (!((flashData & FLASH_DQ7) == (data & FLASH_DQ7))) {
 222                                printf ("_flash_poll(): FLASH_DQ7 & flashData not equal to write value\n");
 223                                error = ERR_PROG_ERROR;
 224                        }
 225                        FLASH_CMD_RESET (dev, addr);
 226                        done = 1;
 227                        break;
 228                }
 229                /*  spin delay */
 230                udelay (10);
 231        }
 232
 233
 234        /*  error update */
 235        if (!done) {
 236                printf ("_flash_poll(): Timeout\n");
 237                error = ERR_TIMOUT;
 238        }
 239
 240        /*  Check the data */
 241        if (!error) {
 242                /*  Read the Data */
 243                flashData = GET__U8 (addr);
 244                if (flashData != data) {
 245                        error = ERR_PROG_ERROR;
 246                        printf ("_flash_poll(): flashData(0x%04x) not equal to data(0x%04x)\n",
 247                                flashData, data);
 248                }
 249        }
 250
 251        return error;
 252}
 253
 254/*-----------------------------------------------------------------------
 255 */
 256static int _flash_check_protection (flash_info_t * info, int s_first, int s_last)
 257{
 258        int sect, prot = 0;
 259
 260        for (sect = s_first; sect <= s_last; sect++)
 261                if (info->protect[sect]) {
 262                        printf ("  Flash sector %d protected.\n", sect);
 263                        prot++;
 264                }
 265        return prot;
 266}
 267
 268static int _detectFlash (FLASH_DEV dev, u32 base, u8 venId, u8 devId)
 269{
 270
 271        u32 baseAddr = base | CACHE_DISABLE_MASK;
 272        u8 vendorId, deviceId;
 273
 274        /*      printf(__FUNCTION__"(): detecting flash @ 0x%08x\n", base); */
 275
 276        /* Send auto select command and read manufacturer info */
 277        FLASH_CMD_SELECT (dev, baseAddr);
 278        vendorId = GET__U8 (baseAddr);
 279        FLASH_CMD_RESET (dev, baseAddr);
 280
 281        /* Send auto select command and read device info */
 282        FLASH_CMD_SELECT (dev, baseAddr);
 283
 284        if (dev == FLASH_DEV_U7_2MB) {
 285                deviceId = GET__U8 (baseAddr + 2);
 286        } else if (dev == FLASH_DEV_U9_512KB) {
 287                deviceId = GET__U8 (baseAddr + 1);
 288        } else {
 289                return 0;
 290        }
 291
 292        FLASH_CMD_RESET (dev, baseAddr);
 293
 294        /* printf (__FUNCTION__"(): found vendorId 0x%04x, deviceId 0x%04x\n",
 295                vendorId, deviceId);
 296         */
 297
 298        return (vendorId == venId) && (deviceId == devId);
 299
 300}
 301
 302/******************************************************************************
 303 *
 304 * Public u-boot interface functions below
 305 *
 306 *****************************************************************************/
 307
 308/***************************************************************************
 309 *
 310 * Flash initialization
 311 *
 312 * This board has two banks of flash, but the base addresses depend on
 313 * how the board is jumpered.
 314 *
 315 * The two flash types are:
 316 *
 317 *   AMD Am29LV160DB (2MB) sectors layout 16KB, 2x8KB, 32KB, 31x64KB
 318 *
 319 *   AMD Am29LV040B  (512KB)  sectors: 8x64KB
 320 *****************************************************************************/
 321
 322unsigned long flash_init (void)
 323{
 324        flash_info_t *info;
 325        u16 i;
 326        u32 flashtest;
 327        s16 amd160 = -1;
 328        u32 amd160base = 0;
 329
 330#if CONFIG_SYS_MAX_FLASH_BANKS == 2
 331        s16 amd040 = -1;
 332        u32 amd040base = 0;
 333#endif
 334
 335        /* configure PHYS_FLASH_1 */
 336        if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_1, 0x1, 0x49)) {
 337                amd160 = 0;
 338                amd160base = PHYS_FLASH_1;
 339#if CONFIG_SYS_MAX_FLASH_BANKS == 1
 340        }
 341#else
 342                if (_detectFlash
 343                    (FLASH_DEV_U9_512KB, PHYS_FLASH_2, 0x1, 0x4F)) {
 344                        amd040 = 1;
 345                        amd040base = PHYS_FLASH_2;
 346                } else {
 347                        printf (__FUNCTION__
 348                                "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
 349                                PHYS_FLASH_2);
 350                }
 351        } else if (_detectFlash (FLASH_DEV_U9_512KB, PHYS_FLASH_1, 0x1, 0x4F)) {
 352                amd040 = 0;
 353                amd040base = PHYS_FLASH_1;
 354                if (_detectFlash (FLASH_DEV_U7_2MB, PHYS_FLASH_2, 0x1, 0x49)) {
 355                        amd160 = 1;
 356                        amd160base = PHYS_FLASH_2;
 357                } else {
 358                        printf (__FUNCTION__
 359                                "(): Unable to detect PHYS_FLASH_2: 0x%08x\n",
 360                                PHYS_FLASH_2);
 361                }
 362        }
 363#endif
 364        else {
 365                printf ("flash_init(): Unable to detect PHYS_FLASH_1: 0x%08x\n",
 366                        PHYS_FLASH_1);
 367        }
 368
 369        /* Configure AMD Am29LV160DB (2MB) */
 370        info = &flash_info[amd160];
 371        info->flash_id = FLASH_DEV_U7_2MB;
 372        info->sector_count = 35;
 373        info->size = 2 * 1024 * 1024;   /* 2MB */
 374        /* 1*16K Boot Block
 375           2*8K Parameter Block
 376           1*32K Small Main Block */
 377        info->start[0] = amd160base;
 378        info->start[1] = amd160base + 0x4000;
 379        info->start[2] = amd160base + 0x6000;
 380        info->start[3] = amd160base + 0x8000;
 381        for (i = 1; i < info->sector_count; i++)
 382                info->start[3 + i] = amd160base + i * (64 * 1024);
 383
 384        for (i = 0; i < info->sector_count; i++) {
 385                /* Write auto select command sequence and query sector protection */
 386                FLASH_CMD_SELECT (info->flash_id,
 387                                  info->start[i] | CACHE_DISABLE_MASK);
 388                flashtest =
 389                        GET__U8 (((info->start[i] + 4) | CACHE_DISABLE_MASK));
 390                FLASH_CMD_RESET (info->flash_id,
 391                                 amd160base | CACHE_DISABLE_MASK);
 392                info->protect[i] = (flashtest & 0x0001);
 393        }
 394
 395        /*
 396         * protect monitor and environment sectors in 2MB flash
 397         */
 398        flash_protect (FLAG_PROTECT_SET,
 399                       amd160base, amd160base + monitor_flash_len - 1, info);
 400
 401        flash_protect (FLAG_PROTECT_SET,
 402                       CONFIG_ENV_ADDR, CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, info);
 403
 404#if CONFIG_SYS_MAX_FLASH_BANKS == 2
 405        /* Configure AMD Am29LV040B (512KB) */
 406        info = &flash_info[amd040];
 407        info->flash_id = FLASH_DEV_U9_512KB;
 408        info->sector_count = 8;
 409        info->size = 512 * 1024;        /* 512KB, 8 x 64KB */
 410        for (i = 0; i < info->sector_count; i++) {
 411                info->start[i] = amd040base + i * (64 * 1024);
 412                /* Write auto select command sequence and query sector protection */
 413                FLASH_CMD_SELECT (info->flash_id,
 414                                  info->start[i] | CACHE_DISABLE_MASK);
 415                flashtest =
 416                        GET__U8 (((info->start[i] + 2) | CACHE_DISABLE_MASK));
 417                FLASH_CMD_RESET (info->flash_id,
 418                                 amd040base | CACHE_DISABLE_MASK);
 419                info->protect[i] = (flashtest & 0x0001);
 420        }
 421#endif
 422
 423        return flash_info[0].size
 424#if CONFIG_SYS_MAX_FLASH_BANKS == 2
 425                + flash_info[1].size
 426#endif
 427                ;
 428}
 429
 430void flash_print_info (flash_info_t * info)
 431{
 432        int i;
 433
 434        if (info->flash_id == FLASH_DEV_U7_2MB) {
 435                printf ("AMD Am29LV160DB (2MB) 16KB,2x8KB,32KB,31x64KB\n");
 436        } else if (info->flash_id == FLASH_DEV_U9_512KB) {
 437                printf ("AMD Am29LV040B  (512KB) 8x64KB\n");
 438        } else {
 439                printf ("Unknown flash_id ...\n");
 440                return;
 441        }
 442
 443        printf ("  Size: %ld KB in %d Sectors\n",
 444                info->size >> 10, info->sector_count);
 445        printf ("  Sector Start Addresses:");
 446        for (i = 0; i < info->sector_count; i++) {
 447                if ((i % 4) == 0)
 448                        printf ("\n   ");
 449                printf (" S%02d @ 0x%08lX%s", i,
 450                        info->start[i], info->protect[i] ? " !" : "  ");
 451        }
 452        printf ("\n");
 453}
 454
 455int flash_erase (flash_info_t * info, int s_first, int s_last)
 456{
 457        u16 i, error = 0;
 458
 459        printf ("\n");
 460
 461        /* check flash protection bits */
 462        if (_flash_check_protection (info, s_first, s_last)) {
 463                printf ("  Flash erase aborted due to protected sectors\n");
 464                return ERR_PROTECTED;
 465        }
 466
 467        if ((s_first < info->sector_count) && (s_first <= s_last)) {
 468                for (i = s_first; i <= s_last && !error; i++) {
 469                        printf ("  Erasing Sector %d @ 0x%08lx ... ", i,
 470                                info->start[i]);
 471                        /* bypass the cache to access the flash memory */
 472                        FLASH_CMD_ERASE_SEC (info->flash_id,
 473                                             (info->
 474                                              start[0] | CACHE_DISABLE_MASK),
 475                                             (info->
 476                                              start[i] | CACHE_DISABLE_MASK));
 477                        /* look for sector to become 0xFF after erase */
 478                        error = _flash_poll (info->flash_id,
 479                                             info->
 480                                             start[i] | CACHE_DISABLE_MASK,
 481                                             0xFF, CONFIG_SYS_FLASH_ERASE_TOUT);
 482                        FLASH_CMD_RESET (info->flash_id,
 483                                         (info->
 484                                          start[0] | CACHE_DISABLE_MASK));
 485                        printf ("done\n");
 486                        if (error) {
 487                                break;
 488                        }
 489                }
 490        } else
 491                error = ERR_INVAL;
 492
 493        return error;
 494}
 495
 496int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 497{
 498        u16 error = 0, i;
 499        u32 n;
 500        u8 *bp, *bps;
 501
 502        /*  Write Setup */
 503        /* bypass the cache to access the flash memory */
 504        FLASH_CMD_UNLOCK_BYPASS (info->flash_id,
 505                                 (info->start[0] | CACHE_DISABLE_MASK));
 506
 507        /*  Write the Data to Flash */
 508
 509        bp = (u8 *) (addr | CACHE_DISABLE_MASK);
 510        bps = (u8 *) src;
 511
 512        for (n = 0; n < cnt && !error; n++, bp++, bps++) {
 513
 514                if (!(n % (cnt / 15))) {
 515                        printf (".");
 516                }
 517
 518                /*  write the flash command for flash memory */
 519                *bp = 0xA0;
 520
 521                /*  Write the data */
 522                *bp = *bps;
 523
 524                /*  Check if the write is done */
 525                for (i = 0; i < 0xff; i++);
 526                error = _flash_poll (info->flash_id, (u32) bp, *bps,
 527                                     CONFIG_SYS_FLASH_WRITE_TOUT);
 528                if (error) {
 529                        return error;
 530                }
 531        }
 532
 533        /*  Reset the Flash Mode to read */
 534        FLASH_CMD_BYPASS_RESET (info->flash_id, info->start[0]);
 535
 536        printf (" ");
 537
 538        return error;
 539}
 540