uboot/board/purple/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003
   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 <asm/inca-ip.h>
  26
  27flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  28
  29typedef unsigned long FLASH_PORT_WIDTH;
  30typedef volatile unsigned long FLASH_PORT_WIDTHV;
  31
  32#define FLASH_ID_MASK   0xFFFFFFFF
  33
  34#define FPW     FLASH_PORT_WIDTH
  35#define FPWV    FLASH_PORT_WIDTHV
  36
  37#define ORMASK(size) ((-size) & OR_AM_MSK)
  38
  39#define FLASH29_REG_ADRS(reg) ((FPWV *)PHYS_FLASH_1 + (reg))
  40
  41/* FLASH29 command register addresses */
  42
  43#define FLASH29_REG_FIRST_CYCLE         FLASH29_REG_ADRS (0x1555)
  44#define FLASH29_REG_SECOND_CYCLE        FLASH29_REG_ADRS (0x2aaa)
  45#define FLASH29_REG_THIRD_CYCLE         FLASH29_REG_ADRS (0x3555)
  46#define FLASH29_REG_FOURTH_CYCLE        FLASH29_REG_ADRS (0x4555)
  47#define FLASH29_REG_FIFTH_CYCLE         FLASH29_REG_ADRS (0x5aaa)
  48#define FLASH29_REG_SIXTH_CYCLE         FLASH29_REG_ADRS (0x6555)
  49
  50/* FLASH29 command definitions */
  51
  52#define FLASH29_CMD_FIRST               0xaaaaaaaa
  53#define FLASH29_CMD_SECOND              0x55555555
  54#define FLASH29_CMD_FOURTH              0xaaaaaaaa
  55#define FLASH29_CMD_FIFTH               0x55555555
  56#define FLASH29_CMD_SIXTH               0x10101010
  57
  58#define FLASH29_CMD_SECTOR              0x30303030
  59#define FLASH29_CMD_PROGRAM             0xa0a0a0a0
  60#define FLASH29_CMD_CHIP_ERASE          0x80808080
  61#define FLASH29_CMD_READ_RESET          0xf0f0f0f0
  62#define FLASH29_CMD_AUTOSELECT          0x90909090
  63#define FLASH29_CMD_READ                0x70707070
  64
  65#define IN_RAM_CMD_READ         0x1
  66#define IN_RAM_CMD_WRITE        0x2
  67
  68#define FLASH_WRITE_CMD ((ulong)(flash_write_cmd) & 0x7)+0xbf008000
  69#define FLASH_READ_CMD  ((ulong)(flash_read_cmd) & 0x7)+0xbf008000
  70
  71typedef void (*FUNCPTR_CP)(ulong *source, ulong *destination, ulong nlongs);
  72typedef void (*FUNCPTR_RD)(int cmd, FPWV * pFA, char * string, int strLen);
  73typedef void (*FUNCPTR_WR)(int cmd, FPWV * pFA, FPW value);
  74
  75static ulong flash_get_size(FPWV *addr, flash_info_t *info);
  76static int write_word(flash_info_t *info, FPWV *dest, FPW data);
  77static void flash_get_offsets(ulong base, flash_info_t *info);
  78static flash_info_t *flash_get_info(ulong base);
  79
  80static void load_cmd(ulong cmd);
  81static ulong in_ram_cmd = 0;
  82
  83
  84/******************************************************************************
  85*
  86* Don't change the program architecture
  87* This architecture assure the program
  88* can be relocated to scratch ram
  89*/
  90static void flash_read_cmd(int cmd, FPWV * pFA, char * string, int strLen)
  91{
  92        int i,j;
  93        FPW temp,temp1;
  94        FPWV *str;
  95
  96        str = (FPWV *)string;
  97
  98        j=  strLen/4;
  99
 100        if(cmd == FLASH29_CMD_AUTOSELECT)
 101           {
 102            *(FLASH29_REG_FIRST_CYCLE)  = FLASH29_CMD_FIRST;
 103            *(FLASH29_REG_SECOND_CYCLE) = FLASH29_CMD_SECOND;
 104            *(FLASH29_REG_THIRD_CYCLE)  = FLASH29_CMD_AUTOSELECT;
 105           }
 106
 107        if(cmd == FLASH29_CMD_READ)
 108           {
 109            i = 0;
 110            while(i<j)
 111            {
 112                temp = *pFA++;
 113                temp1 = *(int *)0xa0000000;
 114                *(int *)0xbf0081f8 = temp1 + temp;
 115                *str++ = temp;
 116                i++;
 117            }
 118           }
 119
 120         if(cmd == FLASH29_CMD_READ_RESET)
 121         {
 122            *(FLASH29_REG_FIRST_CYCLE)  = FLASH29_CMD_FIRST;
 123            *(FLASH29_REG_SECOND_CYCLE) = FLASH29_CMD_SECOND;
 124            *(FLASH29_REG_THIRD_CYCLE)  = FLASH29_CMD_READ_RESET;
 125         }
 126
 127        *(int *)0xbf0081f8 = *(int *)0xa0000000;        /* dummy read switch back to sdram interface */
 128}
 129
 130/******************************************************************************
 131*
 132* Don't change the program architecture
 133* This architecture assure the program
 134* can be relocated to scratch ram
 135*/
 136static void flash_write_cmd(int cmd, FPWV * pFA, FPW value)
 137{
 138        *(FLASH29_REG_FIRST_CYCLE)  = FLASH29_CMD_FIRST;
 139        *(FLASH29_REG_SECOND_CYCLE) = FLASH29_CMD_SECOND;
 140
 141        if (cmd == FLASH29_CMD_SECTOR)
 142           {
 143            *(FLASH29_REG_THIRD_CYCLE)  = FLASH29_CMD_CHIP_ERASE;
 144            *(FLASH29_REG_FOURTH_CYCLE) = FLASH29_CMD_FOURTH;
 145            *(FLASH29_REG_FIFTH_CYCLE)  = FLASH29_CMD_FIFTH;
 146            *pFA                        = FLASH29_CMD_SECTOR;
 147           }
 148
 149        if (cmd == FLASH29_CMD_SIXTH)
 150           {
 151            *(FLASH29_REG_THIRD_CYCLE)  = FLASH29_CMD_CHIP_ERASE;
 152            *(FLASH29_REG_FOURTH_CYCLE) = FLASH29_CMD_FOURTH;
 153            *(FLASH29_REG_FIFTH_CYCLE)  = FLASH29_CMD_FIFTH;
 154            *(FLASH29_REG_SIXTH_CYCLE)  = FLASH29_CMD_SIXTH;
 155           }
 156
 157        if (cmd == FLASH29_CMD_PROGRAM)
 158           {
 159            *(FLASH29_REG_THIRD_CYCLE)  = FLASH29_CMD_PROGRAM;
 160            *pFA = value;
 161           }
 162
 163        if (cmd == FLASH29_CMD_READ_RESET)
 164           {
 165            *(FLASH29_REG_THIRD_CYCLE)  = FLASH29_CMD_READ_RESET;
 166           }
 167
 168        *(int *)0xbf0081f8 = *(int *)0xa0000000;        /* dummy read switch back to sdram interface */
 169}
 170
 171static void load_cmd(ulong cmd)
 172{
 173        ulong *src;
 174        ulong *dst;
 175        FUNCPTR_CP absEntry;
 176        ulong func;
 177
 178        if (in_ram_cmd & cmd) return;
 179
 180        if (cmd == IN_RAM_CMD_READ)
 181        {
 182                func = (ulong)flash_read_cmd;
 183        }
 184        else
 185        {
 186                func = (ulong)flash_write_cmd;
 187        }
 188
 189        src = (ulong *)(func & 0xfffffff8);
 190        dst = (ulong *)0xbf008000;
 191        absEntry = (FUNCPTR_CP)(0xbf0081d0);
 192        absEntry(src,dst,0x38);
 193
 194        in_ram_cmd = cmd;
 195}
 196
 197/*-----------------------------------------------------------------------
 198 * flash_init()
 199 *
 200 * sets up flash_info and returns size of FLASH (bytes)
 201 */
 202unsigned long flash_init (void)
 203{
 204        unsigned long size = 0;
 205        int i;
 206
 207        load_cmd(IN_RAM_CMD_READ);
 208
 209        /* Init: no FLASHes known */
 210        for (i=0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
 211                ulong flashbase = PHYS_FLASH_1;
 212                ulong * buscon = (ulong *) INCA_IP_EBU_EBU_BUSCON0;
 213
 214                /* Disable write protection */
 215                *buscon &= ~INCA_IP_EBU_EBU_BUSCON1_WRDIS;
 216
 217#if 1
 218                memset(&flash_info[i], 0, sizeof(flash_info_t));
 219#endif
 220
 221                flash_info[i].size =
 222                        flash_get_size((FPW *)flashbase, &flash_info[i]);
 223
 224                if (flash_info[i].flash_id == FLASH_UNKNOWN) {
 225                        printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx\n",
 226                        i, flash_info[i].size);
 227                }
 228
 229                size += flash_info[i].size;
 230        }
 231
 232#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
 233        /* monitor protection ON by default */
 234        flash_protect(FLAG_PROTECT_SET,
 235                      CONFIG_SYS_MONITOR_BASE,
 236                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
 237                      flash_get_info(CONFIG_SYS_MONITOR_BASE));
 238#endif
 239
 240#ifdef  CONFIG_ENV_IS_IN_FLASH
 241        /* ENV protection ON by default */
 242        flash_protect(FLAG_PROTECT_SET,
 243                      CONFIG_ENV_ADDR,
 244                      CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
 245                      flash_get_info(CONFIG_ENV_ADDR));
 246#endif
 247
 248        return size;
 249}
 250
 251/*-----------------------------------------------------------------------
 252 */
 253static void flash_get_offsets (ulong base, flash_info_t *info)
 254{
 255        int i;
 256
 257        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD
 258                 && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM160B) {
 259
 260                int bootsect_size[4];   /* number of bytes/boot sector  */
 261                int sect_size;          /* number of bytes/regular sector */
 262
 263                bootsect_size[0] = 0x00008000;
 264                bootsect_size[1] = 0x00004000;
 265                bootsect_size[2] = 0x00004000;
 266                bootsect_size[3] = 0x00010000;
 267                sect_size =        0x00020000;
 268
 269                /* set sector offsets for bottom boot block type        */
 270                for (i = 0; i < info->sector_count; i++) {
 271                        info->start[i] = base;
 272                        base += i < 4 ? bootsect_size[i] : sect_size;
 273                }
 274        }
 275}
 276
 277/*-----------------------------------------------------------------------
 278 */
 279
 280static flash_info_t *flash_get_info(ulong base)
 281{
 282        int i;
 283        flash_info_t * info;
 284
 285        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
 286                info = & flash_info[i];
 287                if (info->start[0] <= base && base < info->start[0] + info->size)
 288                        break;
 289        }
 290
 291        return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
 292}
 293
 294/*-----------------------------------------------------------------------
 295 */
 296
 297void flash_print_info (flash_info_t *info)
 298{
 299        int i;
 300        uchar *boottype;
 301        uchar *bootletter;
 302        char *fmt;
 303        uchar botbootletter[] = "B";
 304        uchar topbootletter[] = "T";
 305        uchar botboottype[] = "bottom boot sector";
 306        uchar topboottype[] = "top boot sector";
 307
 308        if (info->flash_id == FLASH_UNKNOWN) {
 309                printf ("missing or unknown FLASH type\n");
 310                return;
 311        }
 312
 313        switch (info->flash_id & FLASH_VENDMASK) {
 314        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 315        case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
 316        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
 317        case FLASH_MAN_SST:     printf ("SST ");                break;
 318        case FLASH_MAN_STM:     printf ("STM ");                break;
 319        case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
 320        default:                printf ("Unknown Vendor ");     break;
 321        }
 322
 323        /* check for top or bottom boot, if it applies */
 324        if (info->flash_id & FLASH_BTYPE) {
 325                boottype = botboottype;
 326                bootletter = botbootletter;
 327        }
 328        else {
 329                boottype = topboottype;
 330                bootletter = topbootletter;
 331        }
 332
 333        switch (info->flash_id & FLASH_TYPEMASK) {
 334        case FLASH_AM160B:
 335                fmt = "29LV160B%s (16 Mbit, %s)\n";
 336                break;
 337        case FLASH_28F800C3B:
 338        case FLASH_28F800C3T:
 339                fmt = "28F800C3%s (8 Mbit, %s)\n";
 340                break;
 341        case FLASH_INTEL800B:
 342        case FLASH_INTEL800T:
 343                fmt = "28F800B3%s (8 Mbit, %s)\n";
 344                break;
 345        case FLASH_28F160C3B:
 346        case FLASH_28F160C3T:
 347                fmt = "28F160C3%s (16 Mbit, %s)\n";
 348                break;
 349        case FLASH_INTEL160B:
 350        case FLASH_INTEL160T:
 351                fmt = "28F160B3%s (16 Mbit, %s)\n";
 352                break;
 353        case FLASH_28F320C3B:
 354        case FLASH_28F320C3T:
 355                fmt = "28F320C3%s (32 Mbit, %s)\n";
 356                break;
 357        case FLASH_INTEL320B:
 358        case FLASH_INTEL320T:
 359                fmt = "28F320B3%s (32 Mbit, %s)\n";
 360                break;
 361        case FLASH_28F640C3B:
 362        case FLASH_28F640C3T:
 363                fmt = "28F640C3%s (64 Mbit, %s)\n";
 364                break;
 365        case FLASH_INTEL640B:
 366        case FLASH_INTEL640T:
 367                fmt = "28F640B3%s (64 Mbit, %s)\n";
 368                break;
 369        default:
 370                fmt = "Unknown Chip Type\n";
 371                break;
 372        }
 373
 374        printf (fmt, bootletter, boottype);
 375
 376        printf ("  Size: %ld MB in %d Sectors\n",
 377                info->size >> 20,
 378                info->sector_count);
 379
 380        printf ("  Sector Start Addresses:");
 381
 382        for (i=0; i<info->sector_count; ++i) {
 383                if ((i % 5) == 0) {
 384                        printf ("\n   ");
 385                }
 386
 387                printf (" %08lX%s", info->start[i],
 388                        info->protect[i] ? " (RO)" : "     ");
 389        }
 390
 391        printf ("\n");
 392}
 393
 394/*-----------------------------------------------------------------------
 395 */
 396
 397/*
 398 * The following code cannot be run from FLASH!
 399 */
 400
 401ulong flash_get_size (FPWV *addr, flash_info_t *info)
 402{
 403        FUNCPTR_RD absEntry;
 404        FPW retValue;
 405        int flag;
 406
 407        load_cmd(IN_RAM_CMD_READ);
 408        absEntry = (FUNCPTR_RD)FLASH_READ_CMD;
 409
 410        flag = disable_interrupts();
 411        absEntry(FLASH29_CMD_AUTOSELECT,0,0,0);
 412        if (flag) enable_interrupts();
 413
 414        udelay(100);
 415
 416        flag = disable_interrupts();
 417        absEntry(FLASH29_CMD_READ, addr + 1, (char *)&retValue, sizeof(retValue));
 418        absEntry(FLASH29_CMD_READ_RESET,0,0,0);
 419        if (flag) enable_interrupts();
 420
 421        udelay(100);
 422
 423        switch (retValue) {
 424
 425        case (FPW)AMD_ID_LV160B:
 426                info->flash_id += FLASH_AM160B;
 427                info->sector_count = 35;
 428                info->size = 0x00400000;
 429                break;                          /* => 8 or 16 MB        */
 430
 431        default:
 432                info->flash_id = FLASH_UNKNOWN;
 433                info->sector_count = 0;
 434                info->size = 0;
 435                return (0);                     /* => no or unknown flash */
 436        }
 437
 438        flash_get_offsets((ulong)addr, info);
 439
 440        return (info->size);
 441}
 442
 443/*-----------------------------------------------------------------------
 444 */
 445
 446int     flash_erase (flash_info_t *info, int s_first, int s_last)
 447{
 448        FPWV *addr;
 449        int flag, prot, sect;
 450        ulong start, now, last;
 451        int rcode = 0;
 452        FUNCPTR_WR absEntry;
 453
 454        load_cmd(IN_RAM_CMD_WRITE);
 455        absEntry = (FUNCPTR_WR)FLASH_WRITE_CMD;
 456
 457        if ((s_first < 0) || (s_first > s_last)) {
 458                if (info->flash_id == FLASH_UNKNOWN) {
 459                        printf ("- missing\n");
 460                } else {
 461                        printf ("- no sectors to erase\n");
 462                }
 463                return 1;
 464        }
 465
 466        switch (info->flash_id & FLASH_TYPEMASK) {
 467        case FLASH_AM160B:
 468                break;
 469        case FLASH_UNKNOWN:
 470        default:
 471                printf ("Can't erase unknown flash type %08lx - aborted\n",
 472                        info->flash_id);
 473                return 1;
 474        }
 475
 476        prot = 0;
 477        for (sect=s_first; sect<=s_last; ++sect) {
 478                if (info->protect[sect]) {
 479                        prot++;
 480                }
 481        }
 482
 483        if (prot) {
 484                printf ("- Warning: %d protected sectors will not be erased!\n",
 485                        prot);
 486        } else {
 487                printf ("\n");
 488        }
 489
 490        last  = get_timer(0);
 491
 492        /* Start erase on unprotected sectors */
 493        for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
 494
 495                if (info->protect[sect] != 0)   /* protected, skip it */
 496                        continue;
 497
 498                /* Disable interrupts which might cause a timeout here */
 499                flag = disable_interrupts();
 500
 501                addr = (FPWV *)(info->start[sect]);
 502                absEntry(FLASH29_CMD_SECTOR, addr, 0);
 503
 504                /* re-enable interrupts if necessary */
 505                if (flag)
 506                        enable_interrupts();
 507
 508                start = get_timer(0);
 509
 510                while ((now = get_timer(start)) <= CONFIG_SYS_FLASH_ERASE_TOUT) {
 511
 512                        /* show that we're waiting */
 513                        if ((get_timer(last)) > CONFIG_SYS_HZ) {/* every second */
 514                                putc ('.');
 515                                last = get_timer(0);
 516                        }
 517                }
 518
 519                flag = disable_interrupts();
 520                absEntry(FLASH29_CMD_READ_RESET,0,0);
 521                if (flag)
 522                        enable_interrupts();
 523        }
 524
 525        printf (" done\n");
 526        return rcode;
 527}
 528
 529/*-----------------------------------------------------------------------
 530 * Copy memory to flash, returns:
 531 * 0 - OK
 532 * 1 - write timeout
 533 * 2 - Flash not erased
 534 */
 535int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 536{
 537    FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
 538    int bytes;    /* number of bytes to program in current word         */
 539    int left;     /* number of bytes left to program                    */
 540    int i, res;
 541
 542    for (left = cnt, res = 0;
 543         left > 0 && res == 0;
 544         addr += sizeof(data), left -= sizeof(data) - bytes) {
 545
 546        bytes = addr & (sizeof(data) - 1);
 547        addr &= ~(sizeof(data) - 1);
 548
 549        /* combine source and destination data so can program
 550         * an entire word of 16 or 32 bits
 551         */
 552        for (i = 0; i < sizeof(data); i++) {
 553            data <<= 8;
 554            if (i < bytes || i - bytes >= left )
 555                data += *((uchar *)addr + i);
 556            else
 557                data += *src++;
 558        }
 559
 560        res = write_word(info, (FPWV *)addr, data);
 561    }
 562
 563    return (res);
 564}
 565
 566static int write_word (flash_info_t *info, FPWV *dest, FPW data)
 567{
 568    int res = 0;        /* result, assume success       */
 569    FUNCPTR_WR absEntry;
 570    int flag;
 571
 572    /* Check if Flash is (sufficiently) erased */
 573    if ((*dest & data) != data) {
 574        return (2);
 575    }
 576
 577    if (info->start[0] != PHYS_FLASH_1)
 578    {
 579        return (3);
 580    }
 581
 582    load_cmd(IN_RAM_CMD_WRITE);
 583    absEntry = (FUNCPTR_WR)FLASH_WRITE_CMD;
 584
 585    flag = disable_interrupts();
 586    absEntry(FLASH29_CMD_PROGRAM,dest,data);
 587    if (flag) enable_interrupts();
 588
 589    udelay(100);
 590
 591    flag = disable_interrupts();
 592    absEntry(FLASH29_CMD_READ_RESET,0,0);
 593    if (flag) enable_interrupts();
 594
 595    return (res);
 596}
 597