uboot/board/xm250/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
   4 *
   5 * (C) Copyright 2001-2004
   6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27#include <common.h>
  28#include <linux/byteorder/swab.h>
  29
  30
  31flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];    /* info for FLASH chips    */
  32
  33/* Board support for 1 or 2 flash devices */
  34#define FLASH_PORT_WIDTH32
  35#undef FLASH_PORT_WIDTH16
  36
  37#ifdef FLASH_PORT_WIDTH16
  38#define FLASH_PORT_WIDTH                ushort
  39#define FLASH_PORT_WIDTHV               vu_short
  40#define SWAP(x)               __swab16(x)
  41#else
  42#define FLASH_PORT_WIDTH                ulong
  43#define FLASH_PORT_WIDTHV               vu_long
  44#define SWAP(x)               __swab32(x)
  45#endif
  46
  47/* Intel-compatible flash ID */
  48#define INTEL_COMPAT  0x00890089
  49#define INTEL_ALT     0x00B000B0
  50
  51/* Intel-compatible flash commands */
  52#define INTEL_PROGRAM 0x00100010
  53#define INTEL_ERASE   0x00200020
  54#define INTEL_CLEAR   0x00500050
  55#define INTEL_LOCKBIT 0x00600060
  56#define INTEL_PROTECT 0x00010001
  57#define INTEL_STATUS  0x00700070
  58#define INTEL_READID  0x00900090
  59#define INTEL_CONFIRM 0x00D000D0
  60#define INTEL_RESET   0xFFFFFFFF
  61
  62/* Intel-compatible flash status bits */
  63#define INTEL_FINISHED 0x00800080
  64#define INTEL_OK       0x00800080
  65
  66#define FPW        FLASH_PORT_WIDTH
  67#define FPWV   FLASH_PORT_WIDTHV
  68
  69#define mb() __asm__ __volatile__ ("" : : : "memory")
  70
  71/*-----------------------------------------------------------------------
  72 * Functions
  73 */
  74static ulong flash_get_size (FPW *addr, flash_info_t *info);
  75static int write_data (flash_info_t *info, ulong dest, FPW data);
  76static void flash_get_offsets (ulong base, flash_info_t *info);
  77void inline spin_wheel (void);
  78
  79/*-----------------------------------------------------------------------
  80 */
  81
  82unsigned long flash_init (void)
  83{
  84        int i;
  85        ulong size = 0;
  86
  87        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  88                switch (i) {
  89                case 0:
  90                        flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]);
  91                        flash_get_offsets (PHYS_FLASH_1, &flash_info[i]);
  92                        break;
  93                case 1:
  94                        flash_get_size ((FPW *) PHYS_FLASH_2, &flash_info[i]);
  95                        flash_get_offsets (PHYS_FLASH_2, &flash_info[i]);
  96                        break;
  97                default:
  98                        panic ("configured to many flash banks!\n");
  99                        break;
 100                }
 101                size += flash_info[i].size;
 102        }
 103
 104        /* Protect monitor and environment sectors
 105         */
 106        flash_protect ( FLAG_PROTECT_SET,
 107                        CONFIG_SYS_FLASH_BASE,
 108                        CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
 109                        &flash_info[0] );
 110
 111        flash_protect ( FLAG_PROTECT_SET,
 112                        CONFIG_ENV_ADDR,
 113                        CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0] );
 114
 115        return size;
 116}
 117
 118/*-----------------------------------------------------------------------
 119 */
 120static void flash_get_offsets (ulong base, flash_info_t *info)
 121{
 122        int i;
 123
 124        if (info->flash_id == FLASH_UNKNOWN) {
 125                return;
 126        }
 127
 128        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
 129                for (i = 0; i < info->sector_count; i++) {
 130                        info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE);
 131                        info->protect[i] = 0;
 132                }
 133        }
 134}
 135
 136/*-----------------------------------------------------------------------
 137 */
 138void flash_print_info (flash_info_t *info)
 139{
 140        int i;
 141
 142        if (info->flash_id == FLASH_UNKNOWN) {
 143                printf ("missing or unknown FLASH type\n");
 144                return;
 145        }
 146
 147        switch (info->flash_id & FLASH_VENDMASK) {
 148        case FLASH_MAN_INTEL:
 149                printf ("INTEL ");
 150                break;
 151        default:
 152                printf ("Unknown Vendor ");
 153                break;
 154        }
 155
 156        switch (info->flash_id & FLASH_TYPEMASK) {
 157        case FLASH_28F128J3A:
 158                printf ("28F128J3A\n");
 159                break;
 160
 161        case FLASH_28F640J3A:
 162                printf ("28F640J3A\n");
 163                break;
 164        default:
 165                printf ("Unknown Chip Type\n");
 166                break;
 167        }
 168
 169        printf ("  Size: %ld MB in %d Sectors\n",
 170                        info->size >> 20, info->sector_count);
 171
 172        printf ("  Sector Start Addresses:");
 173        for (i = 0; i < info->sector_count; ++i) {
 174                if ((i % 5) == 0)
 175                        printf ("\n   ");
 176                printf (" %08lX%s",
 177                        info->start[i],
 178                        info->protect[i] ? " (RO)" : "     ");
 179        }
 180        printf ("\n");
 181        return;
 182}
 183
 184/*
 185 * The following code cannot be run from FLASH!
 186 */
 187static ulong flash_get_size (FPW *addr, flash_info_t *info)
 188{
 189        volatile FPW value;
 190
 191        /* Write auto select command: read Manufacturer ID */
 192        addr[0x5555] = (FPW) 0x00AA00AA;
 193        addr[0x2AAA] = (FPW) 0x00550055;
 194        addr[0x5555] = (FPW) 0x00900090;
 195
 196        mb ();
 197        value = addr[0];
 198
 199        switch (value) {
 200
 201        case (FPW) INTEL_MANUFACT:
 202                info->flash_id = FLASH_MAN_INTEL;
 203                break;
 204
 205        default:
 206                info->flash_id = FLASH_UNKNOWN;
 207                info->sector_count = 0;
 208                info->size = 0;
 209                addr[0] = (FPW) 0x00FF00FF;     /* restore read mode */
 210                return (0);                     /* no or unknown flash  */
 211        }
 212
 213        mb ();
 214        value = addr[1];                        /* device ID        */
 215
 216        switch (value) {
 217
 218        case (FPW) INTEL_ID_28F128J3A:
 219                info->flash_id += FLASH_28F128J3A;
 220                info->sector_count = 128;
 221                info->size = 0x02000000;
 222                break;                          /* => 32 MB     */
 223
 224        case (FPW) INTEL_ID_28F640J3A:
 225                info->flash_id += FLASH_28F640J3A;
 226                info->sector_count = 64;
 227                info->size = 0x01000000;
 228                break;                          /* => 16 MB     */
 229
 230        default:
 231                info->flash_id = FLASH_UNKNOWN;
 232                break;
 233        }
 234
 235        if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
 236                printf ("** ERROR: sector count %d > max (%d) **\n",
 237                        info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
 238                info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 239        }
 240
 241        addr[0] = (FPW) 0x00FF00FF;             /* restore read mode */
 242
 243        return (info->size);
 244}
 245
 246
 247/*-----------------------------------------------------------------------
 248 */
 249
 250int flash_erase (flash_info_t *info, int s_first, int s_last)
 251{
 252        int flag, prot, sect;
 253        ulong type, start, last;
 254        int rcode = 0;
 255
 256        if ((s_first < 0) || (s_first > s_last)) {
 257                if (info->flash_id == FLASH_UNKNOWN) {
 258                        printf ("- missing\n");
 259                } else {
 260                        printf ("- no sectors to erase\n");
 261                }
 262                return 1;
 263        }
 264
 265        type = (info->flash_id & FLASH_VENDMASK);
 266        if ((type != FLASH_MAN_INTEL)) {
 267                printf ("Can't erase unknown flash type %08lx - aborted\n",
 268                        info->flash_id);
 269                return 1;
 270        }
 271
 272        prot = 0;
 273        for (sect = s_first; sect <= s_last; ++sect) {
 274                if (info->protect[sect]) {
 275                        prot++;
 276                }
 277        }
 278
 279        if (prot) {
 280                printf ("- Warning: %d protected sectors will not be erased!\n",
 281                        prot);
 282        } else {
 283                printf ("\n");
 284        }
 285
 286        start = get_timer (0);
 287        last = start;
 288
 289        /* Disable interrupts which might cause a timeout here */
 290        flag = disable_interrupts ();
 291
 292        /* Start erase on unprotected sectors */
 293        for (sect = s_first; sect <= s_last; sect++) {
 294                if (info->protect[sect] == 0) { /* not protected */
 295                        FPWV *addr = (FPWV *) (info->start[sect]);
 296                        FPW status;
 297
 298                        printf ("Erasing sector %2d ... ", sect);
 299
 300                        /* arm simple, non interrupt dependent timer */
 301                        reset_timer_masked ();
 302
 303                        *addr = (FPW) 0x00500050;       /* clear status register */
 304                        *addr = (FPW) 0x00200020;       /* erase setup */
 305                        *addr = (FPW) 0x00D000D0;       /* erase confirm */
 306
 307                        while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
 308                                if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) {
 309                                        printf ("Timeout\n");
 310                                        *addr = (FPW) 0x00B000B0;       /* suspend erase     */
 311                                        *addr = (FPW) 0x00FF00FF;       /* reset to read mode */
 312                                        rcode = 1;
 313                                        break;
 314                                }
 315                        }
 316
 317                        *addr = 0x00500050;     /* clear status register cmd.   */
 318                        *addr = 0x00FF00FF;     /* resest to read mode          */
 319
 320                        printf (" done\n");
 321                }
 322        }
 323        return rcode;
 324}
 325
 326/*-----------------------------------------------------------------------
 327 * Copy memory to flash, returns:
 328 * 0 - OK
 329 * 1 - write timeout
 330 * 2 - Flash not erased
 331 * 4 - Flash not identified
 332 */
 333
 334int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 335{
 336        ulong cp, wp;
 337        FPW data;
 338        int count, i, l, rc, port_width;
 339
 340        if (info->flash_id == FLASH_UNKNOWN) {
 341                return 4;
 342        }
 343/* get lower word aligned address */
 344#ifdef FLASH_PORT_WIDTH16
 345        wp = (addr & ~1);
 346        port_width = 2;
 347#else
 348        wp = (addr & ~3);
 349        port_width = 4;
 350#endif
 351
 352        /*
 353         * handle unaligned start bytes
 354         */
 355        if ((l = addr - wp) != 0) {
 356                data = 0;
 357                for (i = 0, cp = wp; i < l; ++i, ++cp) {
 358                        data = (data << 8) | (*(uchar *) cp);
 359                }
 360                for (; i < port_width && cnt > 0; ++i) {
 361                        data = (data << 8) | *src++;
 362                        --cnt;
 363                        ++cp;
 364                }
 365                for (; cnt == 0 && i < port_width; ++i, ++cp) {
 366                        data = (data << 8) | (*(uchar *) cp);
 367                }
 368
 369                if ((rc = write_data (info, wp, SWAP (data))) != 0) {
 370                        return (rc);
 371                }
 372                wp += port_width;
 373        }
 374
 375        /*
 376         * handle word aligned part
 377         */
 378        count = 0;
 379        while (cnt >= port_width) {
 380                data = 0;
 381                for (i = 0; i < port_width; ++i) {
 382                        data = (data << 8) | *src++;
 383                }
 384                if ((rc = write_data (info, wp, SWAP (data))) != 0) {
 385                        return (rc);
 386                }
 387                wp += port_width;
 388                cnt -= port_width;
 389                if (count++ > 0x800) {
 390                        spin_wheel ();
 391                        count = 0;
 392                }
 393        }
 394
 395        if (cnt == 0) {
 396                return (0);
 397        }
 398
 399        /*
 400         * handle unaligned tail bytes
 401         */
 402        data = 0;
 403        for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) {
 404                data = (data << 8) | *src++;
 405                --cnt;
 406        }
 407        for (; i < port_width; ++i, ++cp) {
 408                data = (data << 8) | (*(uchar *) cp);
 409        }
 410
 411        return (write_data (info, wp, SWAP (data)));
 412}
 413
 414/*-----------------------------------------------------------------------
 415 * Write a word or halfword to Flash, returns:
 416 * 0 - OK
 417 * 1 - write timeout
 418 * 2 - Flash not erased
 419 */
 420static int write_data (flash_info_t *info, ulong dest, FPW data)
 421{
 422        FPWV *addr = (FPWV *) dest;
 423        ulong status;
 424        int flag;
 425
 426        /* Check if Flash is (sufficiently) erased */
 427        if ((*addr & data) != data) {
 428                printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr);
 429                return (2);
 430        }
 431        /* Disable interrupts which might cause a timeout here */
 432        flag = disable_interrupts ();
 433
 434        *addr = (FPW) 0x00400040;       /* write setup */
 435        *addr = data;
 436
 437        /* arm simple, non interrupt dependent timer */
 438        reset_timer_masked ();
 439
 440        /* wait while polling the status register */
 441        while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
 442                if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) {
 443                        *addr = (FPW) 0x00FF00FF;       /* restore read mode */
 444                        return (1);
 445                }
 446        }
 447
 448        *addr = (FPW) 0x00FF00FF;       /* restore read mode */
 449
 450        return (0);
 451}
 452
 453void inline spin_wheel (void)
 454{
 455        static int p = 0;
 456        static char w[] = "\\/-";
 457
 458        printf ("\010%c", w[p]);
 459        (++p == 3) ? (p = 0) : 0;
 460}
 461
 462/*-----------------------------------------------------------------------
 463 * Set/Clear sector's lock bit, returns:
 464 * 0 - OK
 465 * 1 - Error (timeout, voltage problems, etc.)
 466 */
 467int flash_real_protect(flash_info_t *info, long sector, int prot)
 468{
 469        int i;
 470        int rc = 0;
 471        vu_long *addr = (vu_long *)(info->start[sector]);
 472        int flag = disable_interrupts();
 473
 474        *addr = INTEL_CLEAR;    /* Clear status register */
 475        if (prot) {                     /* Set sector lock bit */
 476                *addr = INTEL_LOCKBIT;  /* Sector lock bit */
 477                *addr = INTEL_PROTECT;  /* set */
 478        }
 479        else {                          /* Clear sector lock bit */
 480                *addr = INTEL_LOCKBIT;  /* All sectors lock bits */
 481                *addr = INTEL_CONFIRM;  /* clear */
 482        }
 483
 484        reset_timer_masked ();
 485
 486        while ((*addr & INTEL_FINISHED) != INTEL_FINISHED) {
 487                if (get_timer_masked () > CONFIG_SYS_FLASH_UNLOCK_TOUT) {
 488                        printf("Flash lock bit operation timed out\n");
 489                        rc = 1;
 490                        break;
 491                }
 492        }
 493
 494        if (*addr != INTEL_OK) {
 495                printf("Flash lock bit operation failed at %08X, CSR=%08X\n",
 496                       (uint)addr, (uint)*addr);
 497                rc = 1;
 498        }
 499
 500        if (!rc)
 501                info->protect[sector] = prot;
 502
 503        /*
 504         * Clear lock bit command clears all sectors lock bits, so
 505         * we have to restore lock bits of protected sectors.
 506         */
 507        if (!prot)
 508        {
 509                for (i = 0; i < info->sector_count; i++)
 510                {
 511                        if (info->protect[i])
 512                        {
 513                                reset_timer_masked ();
 514                                addr = (vu_long *)(info->start[i]);
 515                                *addr = INTEL_LOCKBIT;  /* Sector lock bit */
 516                                *addr = INTEL_PROTECT;  /* set */
 517                                while ((*addr & INTEL_FINISHED) != INTEL_FINISHED)
 518                                {
 519                                        if (get_timer_masked () > CONFIG_SYS_FLASH_UNLOCK_TOUT)
 520                                        {
 521                                                printf("Flash lock bit operation timed out\n");
 522                                                rc = 1;
 523                                                break;
 524                                        }
 525                                }
 526                        }
 527                }
 528        }
 529
 530        if (flag)
 531                enable_interrupts();
 532
 533        *addr = INTEL_RESET;            /* Reset to read array mode */
 534
 535        return rc;
 536}
 537