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