uboot/board/cogent/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Wolfgang Denk, DENX Software Engineering, wd@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#include <common.h>
  25#include <board/cogent/flash.h>
  26
  27flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  28
  29#if defined(CONFIG_ENV_IS_IN_FLASH)
  30# ifndef  CONFIG_ENV_ADDR
  31#  define CONFIG_ENV_ADDR       (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
  32# endif
  33# ifndef  CONFIG_ENV_SIZE
  34#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
  35# endif
  36# ifndef  CONFIG_ENV_SECT_SIZE
  37#  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
  38# endif
  39#endif
  40
  41/*-----------------------------------------------------------------------
  42 * Functions
  43 */
  44static int write_word (flash_info_t *info, ulong dest, ulong data);
  45
  46/*-----------------------------------------------------------------------
  47 */
  48
  49
  50#if defined(CONFIG_CMA302)
  51
  52/*
  53 * probe for the existence of flash at address "addr"
  54 * 0 = yes, 1 = bad Manufacturer's Id, 2 = bad Device Id
  55 */
  56static int
  57c302f_probe_word(c302f_addr_t addr)
  58{
  59        /* reset the flash */
  60        *addr = C302F_BNK_CMD_RST;
  61
  62        /* check the manufacturer id */
  63        *addr = C302F_BNK_CMD_RD_ID;
  64        if (*C302F_BNK_ADDR_MAN(addr) != C302F_BNK_RD_ID_MAN)
  65                return 1;
  66
  67        /* check the device id */
  68        *addr = C302F_BNK_CMD_RD_ID;
  69        if (*C302F_BNK_ADDR_DEV(addr) != C302F_BNK_RD_ID_DEV)
  70                return 2;
  71
  72#ifdef FLASH_DEBUG
  73        {
  74                int i;
  75
  76                printf("\nMaster Lock Config = 0x%08lx\n",
  77                        *C302F_BNK_ADDR_CFGM(addr));
  78                for (i = 0; i < C302F_BNK_NBLOCKS; i++)
  79                        printf("Block %2d Lock Config = 0x%08lx\n",
  80                                i, *C302F_BNK_ADDR_CFG(i, addr));
  81        }
  82#endif
  83
  84        /* reset the flash again */
  85        *addr = C302F_BNK_CMD_RST;
  86
  87        return 0;
  88}
  89
  90/*
  91 * probe for Cogent CMA302 flash module at address "base" and store
  92 * info for any found into flash_info entry "fip". Must find at least
  93 * one bank.
  94 */
  95static void
  96c302f_probe(flash_info_t *fip, c302f_addr_t base)
  97{
  98        c302f_addr_t addr, eaddr;
  99        int nbanks;
 100
 101        fip->size = 0L;
 102        fip->sector_count = 0;
 103
 104        addr = base;
 105        eaddr = C302F_BNK_ADDR_BASE(addr, C302F_MAX_BANKS);
 106        nbanks = 0;
 107
 108        while (addr < eaddr) {
 109                c302f_addr_t addrw, eaddrw, addrb;
 110                int i, osc, nsc;
 111
 112                addrw = addr;
 113                eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);
 114
 115                while (addrw < eaddrw)
 116                        if (c302f_probe_word(addrw++) != 0)
 117                                goto out;
 118
 119                /* bank exists - append info for this bank to *fip */
 120                fip->flash_id = FLASH_MAN_INTEL|FLASH_28F008S5;
 121                fip->size += C302F_BNK_SIZE;
 122                osc = fip->sector_count;
 123                fip->sector_count += C302F_BNK_NBLOCKS;
 124                if ((nsc = fip->sector_count) >= CONFIG_SYS_MAX_FLASH_SECT)
 125                        panic("Too many sectors in flash at address 0x%08lx\n",
 126                                (unsigned long)base);
 127
 128                addrb = addr;
 129                for (i = osc; i < nsc; i++) {
 130                        fip->start[i] = (ulong)addrb;
 131                        fip->protect[i] = 0;
 132                        addrb = C302F_BNK_ADDR_NEXT_BLK(addrb);
 133                }
 134
 135                addr = C302F_BNK_ADDR_NEXT_BNK(addr);
 136                nbanks++;
 137        }
 138
 139out:
 140        if (nbanks == 0)
 141                panic("ERROR: no flash found at address 0x%08lx\n",
 142                        (unsigned long)base);
 143}
 144
 145static void
 146c302f_reset(flash_info_t *info, int sect)
 147{
 148        c302f_addr_t addrw, eaddrw;
 149
 150        addrw = (c302f_addr_t)info->start[sect];
 151        eaddrw = C302F_BNK_ADDR_NEXT_WORD(addrw);
 152
 153        while (addrw < eaddrw) {
 154#ifdef FLASH_DEBUG
 155                printf("  writing reset cmd to addr 0x%08lx\n",
 156                        (unsigned long)addrw);
 157#endif
 158                *addrw = C302F_BNK_CMD_RST;
 159                addrw++;
 160        }
 161}
 162
 163static void
 164c302f_erase_init(flash_info_t *info, int sect)
 165{
 166        c302f_addr_t addrw, saddrw, eaddrw;
 167        int flag;
 168
 169#ifdef FLASH_DEBUG
 170        printf("0x%08lx C302F_BNK_CMD_PROG\n", C302F_BNK_CMD_PROG);
 171        printf("0x%08lx C302F_BNK_CMD_ERASE1\n", C302F_BNK_CMD_ERASE1);
 172        printf("0x%08lx C302F_BNK_CMD_ERASE2\n", C302F_BNK_CMD_ERASE2);
 173        printf("0x%08lx C302F_BNK_CMD_CLR_STAT\n", C302F_BNK_CMD_CLR_STAT);
 174        printf("0x%08lx C302F_BNK_CMD_RST\n", C302F_BNK_CMD_RST);
 175        printf("0x%08lx C302F_BNK_STAT_RDY\n", C302F_BNK_STAT_RDY);
 176        printf("0x%08lx C302F_BNK_STAT_ERR\n", C302F_BNK_STAT_ERR);
 177#endif
 178
 179        saddrw = (c302f_addr_t)info->start[sect];
 180        eaddrw = C302F_BNK_ADDR_NEXT_WORD(saddrw);
 181
 182#ifdef FLASH_DEBUG
 183        printf("erasing sector %d, start addr = 0x%08lx "
 184                "(bank next word addr = 0x%08lx)\n", sect,
 185                (unsigned long)saddrw, (unsigned long)eaddrw);
 186#endif
 187
 188        /* Disable intrs which might cause a timeout here */
 189        flag = disable_interrupts();
 190
 191        for (addrw = saddrw; addrw < eaddrw; addrw++) {
 192#ifdef FLASH_DEBUG
 193                printf("  writing erase cmd to addr 0x%08lx\n",
 194                        (unsigned long)addrw);
 195#endif
 196                *addrw = C302F_BNK_CMD_ERASE1;
 197                *addrw = C302F_BNK_CMD_ERASE2;
 198        }
 199
 200        /* re-enable interrupts if necessary */
 201        if (flag)
 202                enable_interrupts();
 203}
 204
 205static int
 206c302f_erase_poll(flash_info_t *info, int sect)
 207{
 208        c302f_addr_t addrw, saddrw, eaddrw;
 209        int sectdone, haderr;
 210
 211        saddrw = (c302f_addr_t)info->start[sect];
 212        eaddrw = C302F_BNK_ADDR_NEXT_WORD(saddrw);
 213
 214        sectdone = 1;
 215        haderr = 0;
 216
 217        for (addrw = saddrw; addrw < eaddrw; addrw++) {
 218                c302f_word_t stat = *addrw;
 219
 220#ifdef FLASH_DEBUG
 221                printf("  checking status at addr "
 222                        "0x%08lx [0x%08lx]\n",
 223                        (unsigned long)addrw, stat);
 224#endif
 225                if ((stat & C302F_BNK_STAT_RDY) != C302F_BNK_STAT_RDY)
 226                        sectdone = 0;
 227                else if ((stat & C302F_BNK_STAT_ERR) != 0) {
 228                        printf(" failed on sector %d "
 229                                "(stat = 0x%08lx) at "
 230                                "address 0x%08lx\n",
 231                                sect, stat,
 232                                (unsigned long)addrw);
 233                        *addrw = C302F_BNK_CMD_CLR_STAT;
 234                        haderr = 1;
 235                }
 236        }
 237
 238        if (haderr)
 239                return (-1);
 240        else
 241                return (sectdone);
 242}
 243
 244static int
 245c302f_write_word(c302f_addr_t addr, c302f_word_t value)
 246{
 247        c302f_word_t stat;
 248        ulong start;
 249        int flag, retval;
 250
 251        /* Disable interrupts which might cause a timeout here */
 252        flag = disable_interrupts();
 253
 254        *addr = C302F_BNK_CMD_PROG;
 255
 256        *addr = value;
 257
 258        /* re-enable interrupts if necessary */
 259        if (flag)
 260                enable_interrupts();
 261
 262        retval = 0;
 263
 264        /* data polling for D7 */
 265        start = get_timer (0);
 266        do {
 267                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 268                        retval = 1;
 269                        goto done;
 270                }
 271                stat = *addr;
 272        } while ((stat & C302F_BNK_STAT_RDY) != C302F_BNK_STAT_RDY);
 273
 274        if ((stat & C302F_BNK_STAT_ERR) != 0) {
 275                printf("flash program failed (stat = 0x%08lx) "
 276                        "at address 0x%08lx\n", (ulong)stat, (ulong)addr);
 277                *addr = C302F_BNK_CMD_CLR_STAT;
 278                retval = 3;
 279        }
 280
 281done:
 282        /* reset to read mode */
 283        *addr = C302F_BNK_CMD_RST;
 284
 285        return (retval);
 286}
 287
 288#endif  /* CONFIG_CMA302 */
 289
 290unsigned long
 291flash_init(void)
 292{
 293        unsigned long total;
 294        int i;
 295        flash_info_t *fip;
 296
 297        /* Init: no FLASHes known */
 298        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
 299                flash_info[i].flash_id = FLASH_UNKNOWN;
 300        }
 301
 302        fip = &flash_info[0];
 303        total = 0L;
 304
 305#if defined(CONFIG_CMA302)
 306        c302f_probe(fip, (c302f_addr_t)CONFIG_SYS_FLASH_BASE);
 307        total += fip->size;
 308        fip++;
 309#endif
 310
 311#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
 312        /* not yet ...
 313        cmbf_probe(fip, (cmbf_addr_t)CMA_MB_FLASH_BASE);
 314        total += fip->size;
 315        fip++;
 316        */
 317#endif
 318
 319        /*
 320         * protect monitor and environment sectors
 321         */
 322
 323#if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
 324        flash_protect(FLAG_PROTECT_SET,
 325                      CONFIG_SYS_MONITOR_BASE,
 326                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
 327                      &flash_info[0]);
 328#endif
 329
 330#ifdef  CONFIG_ENV_IS_IN_FLASH
 331        /* ENV protection ON by default */
 332        flash_protect(FLAG_PROTECT_SET,
 333                      CONFIG_ENV_ADDR,
 334                      CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
 335                      &flash_info[0]);
 336#endif
 337        return total;
 338}
 339
 340/*-----------------------------------------------------------------------
 341 */
 342void
 343flash_print_info(flash_info_t *info)
 344{
 345        int i;
 346
 347        if (info->flash_id == FLASH_UNKNOWN) {
 348                printf ("missing or unknown FLASH type\n");
 349                return;
 350        }
 351
 352        switch (info->flash_id & FLASH_VENDMASK) {
 353        case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
 354        default:                printf ("Unknown Vendor ");     break;
 355        }
 356
 357        switch (info->flash_id & FLASH_TYPEMASK) {
 358        case FLASH_28F008S5:    printf ("28F008S5\n");
 359                                break;
 360        default:                printf ("Unknown Chip Type\n");
 361                                break;
 362        }
 363
 364        printf ("  Size: %ld MB in %d Sectors\n",
 365                info->size >> 20, info->sector_count);
 366
 367        printf ("  Sector Start Addresses:");
 368        for (i=0; i<info->sector_count; ++i) {
 369                if ((i % 4) == 0)
 370                        printf ("\n   ");
 371                printf (" %2d - %08lX%s", i,
 372                        info->start[i],
 373                        info->protect[i] ? " (RO)" : "     "
 374                );
 375        }
 376        printf ("\n");
 377        return;
 378}
 379
 380/*-----------------------------------------------------------------------
 381 */
 382
 383
 384/*-----------------------------------------------------------------------
 385 */
 386
 387/*
 388 * The following code cannot be run from FLASH!
 389 */
 390
 391int
 392flash_erase(flash_info_t *info, int s_first, int s_last)
 393{
 394        int prot, sect, haderr;
 395        ulong start, now, last;
 396        void (*erase_init)(flash_info_t *, int);
 397        int (*erase_poll)(flash_info_t *, int);
 398        void (*reset)(flash_info_t *, int);
 399        int rcode = 0;
 400
 401#ifdef FLASH_DEBUG
 402        printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
 403                "  Bank # %d: ", s_last - s_first + 1, s_first, s_last,
 404                (info - flash_info) + 1);
 405        flash_print_info(info);
 406#endif
 407
 408        if ((s_first < 0) || (s_first > s_last)) {
 409                if (info->flash_id == FLASH_UNKNOWN) {
 410                        printf ("- missing\n");
 411                } else {
 412                        printf ("- no sectors to erase\n");
 413                }
 414                return 1;
 415        }
 416
 417        switch (info->flash_id) {
 418
 419#if defined(CONFIG_CMA302)
 420        case FLASH_MAN_INTEL|FLASH_28F008S5:
 421                erase_init = c302f_erase_init;
 422                erase_poll = c302f_erase_poll;
 423                reset = c302f_reset;
 424                break;
 425#endif
 426
 427#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
 428        case FLASH_MAN_INTEL|FLASH_28F800_B:
 429        case FLASH_MAN_AMD|FLASH_AM29F800B:
 430                /* not yet ...
 431                erase_init = cmbf_erase_init;
 432                erase_poll = cmbf_erase_poll;
 433                reset = cmbf_reset;
 434                break;
 435                */
 436#endif
 437
 438        default:
 439                printf ("Flash type %08lx not supported - aborted\n",
 440                        info->flash_id);
 441                return 1;
 442        }
 443
 444        prot = 0;
 445        for (sect=s_first; sect<=s_last; ++sect) {
 446                if (info->protect[sect]) {
 447                        prot++;
 448                }
 449        }
 450
 451        if (prot) {
 452                printf("- Warning: %d protected sector%s will not be erased!\n",
 453                        prot, (prot > 1 ? "s" : ""));
 454        }
 455
 456        start = get_timer (0);
 457        last = 0;
 458        haderr = 0;
 459
 460        for (sect = s_first; sect <= s_last; sect++) {
 461                if (info->protect[sect] == 0) { /* not protected */
 462                        ulong estart;
 463                        int sectdone;
 464
 465                        (*erase_init)(info, sect);
 466
 467                        /* wait at least 80us - let's wait 1 ms */
 468                        udelay (1000);
 469
 470                        estart = get_timer(start);
 471
 472                        do {
 473                                now = get_timer(start);
 474
 475                                if (now - estart > CONFIG_SYS_FLASH_ERASE_TOUT) {
 476                                        printf ("Timeout (sect %d)\n", sect);
 477                                        haderr = 1;
 478                                        break;
 479                                }
 480
 481#ifndef FLASH_DEBUG
 482                                /* show that we're waiting */
 483                                if ((now - last) > 1000) { /* every second */
 484                                        putc ('.');
 485                                        last = now;
 486                                }
 487#endif
 488
 489                                sectdone = (*erase_poll)(info, sect);
 490
 491                                if (sectdone < 0) {
 492                                        haderr = 1;
 493                                        break;
 494                                }
 495
 496                        } while (!sectdone);
 497
 498                        if (haderr)
 499                                break;
 500                }
 501        }
 502
 503        if (haderr > 0) {
 504                printf (" failed\n");
 505                rcode = 1;
 506        }
 507        else
 508                printf (" done\n");
 509
 510        /* reset to read mode */
 511        for (sect = s_first; sect <= s_last; sect++) {
 512                if (info->protect[sect] == 0) { /* not protected */
 513                        (*reset)(info, sect);
 514                }
 515        }
 516        return rcode;
 517}
 518
 519/*-----------------------------------------------------------------------
 520 * Copy memory to flash, returns:
 521 * 0 - OK
 522 * 1 - write timeout
 523 * 2 - Flash not erased
 524 * 3 - write error
 525 */
 526
 527int
 528write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 529{
 530        ulong cp, wp, data;
 531        int i, l, rc;
 532        ulong start, now, last;
 533
 534        wp = (addr & ~3);       /* get lower word aligned address */
 535
 536        /*
 537         * handle unaligned start bytes
 538         */
 539        if ((l = addr - wp) != 0) {
 540                data = 0;
 541                for (i=0, cp=wp; i<l; ++i, ++cp) {
 542                        data = (data << 8) | (*(uchar *)cp);
 543                }
 544                for (; i<4 && cnt>0; ++i) {
 545                        data = (data << 8) | *src++;
 546                        --cnt;
 547                        ++cp;
 548                }
 549                for (; cnt==0 && i<4; ++i, ++cp) {
 550                        data = (data << 8) | (*(uchar *)cp);
 551                }
 552
 553                if ((rc = write_word(info, wp, data)) != 0) {
 554                        return (rc);
 555                }
 556                wp += 4;
 557        }
 558
 559        /*
 560         * handle word aligned part
 561         */
 562        start = get_timer (0);
 563        last = 0;
 564        while (cnt >= 4) {
 565                data = 0;
 566                for (i=0; i<4; ++i) {
 567                        data = (data << 8) | *src++;
 568                }
 569                if ((rc = write_word(info, wp, data)) != 0) {
 570                        return (rc);
 571                }
 572                wp  += 4;
 573                cnt -= 4;
 574
 575                /* show that we're waiting */
 576                now = get_timer(start);
 577                if ((now - last) > 1000) {      /* every second */
 578                        putc ('.');
 579                        last = now;
 580                }
 581        }
 582
 583        if (cnt == 0) {
 584                return (0);
 585        }
 586
 587        /*
 588         * handle unaligned tail bytes
 589         */
 590        data = 0;
 591        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 592                data = (data << 8) | *src++;
 593                --cnt;
 594        }
 595        for (; i<4; ++i, ++cp) {
 596                data = (data << 8) | (*(uchar *)cp);
 597        }
 598
 599        return (write_word(info, wp, data));
 600}
 601
 602/*-----------------------------------------------------------------------
 603 * Write a word to Flash, returns:
 604 * 0 - OK
 605 * 1 - write timeout
 606 * 2 - Flash not erased
 607 * 3 - write error
 608 */
 609static int
 610write_word(flash_info_t *info, ulong dest, ulong data)
 611{
 612        int retval;
 613
 614        /* Check if Flash is (sufficiently) erased */
 615        if ((*(ulong *)dest & data) != data) {
 616                return (2);
 617        }
 618
 619        switch (info->flash_id) {
 620
 621#if defined(CONFIG_CMA302)
 622        case FLASH_MAN_INTEL|FLASH_28F008S5:
 623                retval = c302f_write_word((c302f_addr_t)dest, (c302f_word_t)data);
 624                break;
 625#endif
 626
 627#if (CMA_MB_CAPS & CMA_MB_CAP_FLASH)
 628        case FLASH_MAN_INTEL|FLASH_28F800_B:
 629        case FLASH_MAN_AMD|FLASH_AM29F800B:
 630                /* not yet ...
 631                retval = cmbf_write_word((cmbf_addr_t)dest, (cmbf_word_t)data);
 632                */
 633                retval = 3;
 634                break;
 635#endif
 636
 637        default:
 638                printf ("Flash type %08lx not supported - aborted\n",
 639                        info->flash_id);
 640                retval = 3;
 641                break;
 642        }
 643
 644        return (retval);
 645}
 646
 647/*-----------------------------------------------------------------------
 648 */
 649