uboot/board/v37/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/*
  25 * Yoo. Jonghoon, IPone, yooth@ipone.co.kr
  26 * U-Boot port on RPXlite board
  27 *
  28 * Some of flash control words are modified. (from 2x16bit device
  29 * to 4x8bit device)
  30 * RPXLite board I tested has only 4 AM29LV800BB devices. Other devices
  31 * are not tested.
  32 *
  33 * (?) Does an RPXLite board which
  34 *      does not use AM29LV800 flash memory exist ?
  35 *      I don't know...
  36 */
  37
  38#include <common.h>
  39#include <mpc8xx.h>
  40
  41flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  42
  43/*-----------------------------------------------------------------------
  44 * Functions
  45 */
  46static ulong flash_get_size ( short manu, short dev_id, flash_info_t *info);
  47static int write_word (flash_info_t *info, ulong dest, ulong data);
  48static void flash_get_offsets (ulong base, flash_info_t *info, int two_chips);
  49static void flash_get_id_word( void *ptr,  short *ptr_manuf, short *ptr_dev_id);
  50static void flash_get_id_long( void *ptr,  short *ptr_manuf, short *ptr_dev_id);
  51
  52/*-----------------------------------------------------------------------
  53 */
  54
  55unsigned long flash_init (void)
  56{
  57        volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR;
  58        volatile memctl8xx_t *memctl = &immap->im_memctl;
  59        unsigned long size_b0, size_b1;
  60        short manu, dev_id;
  61        int i;
  62
  63        /* Init: no FLASHes known */
  64        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  65                flash_info[i].flash_id = FLASH_UNKNOWN;
  66        }
  67
  68        /* Do sizing to get full correct info */
  69
  70        flash_get_id_word((void*)CONFIG_SYS_FLASH_BASE0,&manu,&dev_id);
  71
  72        size_b0 = flash_get_size(manu, dev_id, &flash_info[0]);
  73
  74        flash_get_offsets (CONFIG_SYS_FLASH_BASE0, &flash_info[0],0);
  75
  76        memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (0 - size_b0);
  77
  78#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE0
  79        /* monitor protection ON by default */
  80        flash_protect(FLAG_PROTECT_SET,
  81                      CONFIG_SYS_MONITOR_BASE,
  82                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  83                      &flash_info[0]);
  84#endif
  85
  86        flash_get_id_long((void*)CONFIG_SYS_FLASH_BASE1,&manu,&dev_id);
  87
  88        size_b1 = 2 * flash_get_size(manu, dev_id, &flash_info[1]);
  89
  90        flash_get_offsets(CONFIG_SYS_FLASH_BASE1, &flash_info[1],1);
  91
  92        memctl->memc_or1 = CONFIG_SYS_OR_TIMING_FLASH | (0 - size_b1);
  93
  94        flash_info[0].size = size_b0;
  95        flash_info[1].size = size_b1;
  96
  97        return (size_b0+size_b1);
  98}
  99
 100/*-----------------------------------------------------------------------
 101 */
 102static void flash_get_offsets (ulong base, flash_info_t *info, int two_chips)
 103{
 104        int i, addr_shift;
 105        vu_short *addr = (vu_short*)base;
 106
 107        addr[0x555] = 0x00AA ;
 108        addr[0xAAA] = 0x0055 ;
 109        addr[0x555] = 0x0090 ;
 110
 111        addr_shift = (two_chips ? 2 : 1 );
 112
 113        /* set up sector start address table */
 114        if (info->flash_id & FLASH_BTYPE) {
 115                /* set sector offsets for bottom boot block type        */
 116                info->start[0] = base + (0x00000000<<addr_shift);
 117                info->start[1] = base + (0x00002000<<addr_shift);
 118                info->start[2] = base + (0x00003000<<addr_shift);
 119                info->start[3] = base + (0x00004000<<addr_shift);
 120                for (i = 4; i < info->sector_count; i++) {
 121                        info->start[i] = base + ((i-3) * (0x00008000<<addr_shift)) ;
 122                }
 123        } else {
 124                /* set sector offsets for top boot block type           */
 125                i = info->sector_count - 1;
 126                info->start[i--] = base + info->size - (0x00002000<<addr_shift);
 127                info->start[i--] = base + info->size - (0x00003000<<addr_shift);
 128                info->start[i--] = base + info->size - (0x00004000<<addr_shift);
 129                for (; i >= 0; i--) {
 130                        info->start[i] = base + i * (0x00008000<<addr_shift);
 131                }
 132        }
 133
 134        /* check for protected sectors */
 135        for (i = 0; i < info->sector_count; i++) {
 136                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 137                /* D0 = 1 if protected */
 138                addr = (vu_short *)(info->start[i]);
 139                info->protect[i] = addr[1<<addr_shift] & 1 ;
 140        }
 141
 142        addr = (vu_short *)info->start[0];
 143        *addr = 0xF0F0; /* reset bank */
 144}
 145
 146/*-----------------------------------------------------------------------
 147 */
 148void flash_print_info  (flash_info_t *info)
 149{
 150        int i;
 151
 152        if (info->flash_id == FLASH_UNKNOWN) {
 153                printf ("missing or unknown FLASH type\n");
 154                return;
 155        }
 156
 157        switch (info->flash_id & FLASH_VENDMASK) {
 158        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 159        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
 160        case FLASH_MAN_TOSH:    printf ("TOSHIBA ");            break;
 161        default:                printf ("Unknown Vendor ");     break;
 162        }
 163
 164        switch (info->flash_id & FLASH_TYPEMASK) {
 165        case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
 166                                break;
 167        case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
 168                                break;
 169        case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
 170                                break;
 171        case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
 172                                break;
 173        case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
 174                                break;
 175        case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
 176                                break;
 177        case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
 178                                break;
 179        case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
 180                                break;
 181        default:                printf ("Unknown Chip Type\n");
 182                                break;
 183        }
 184
 185        printf ("  Size: %ld MB in %d Sectors\n",
 186                info->size >> 20, info->sector_count);
 187
 188        printf ("  Sector Start Addresses:");
 189        for (i=0; i<info->sector_count; ++i) {
 190                if ((i % 5) == 0)
 191                        printf ("\n   ");
 192                printf (" %08lX%s",
 193                        info->start[i],
 194                        info->protect[i] ? " (RO)" : "     "
 195                );
 196        }
 197        printf ("\n");
 198}
 199
 200/*-----------------------------------------------------------------------
 201 */
 202
 203
 204/*-----------------------------------------------------------------------
 205 */
 206
 207/*
 208 * The following code cannot be run from FLASH!
 209 */
 210
 211static void flash_get_id_word( void *ptr,  short *ptr_manuf, short *ptr_dev_id)
 212{
 213        vu_short *addr = (vu_short*)ptr;
 214
 215        addr[0x555] = 0x00AA ;
 216        addr[0xAAA] = 0x0055 ;
 217        addr[0x555] = 0x0090 ;
 218
 219        *ptr_manuf  = addr[0];
 220        *ptr_dev_id = addr[1];
 221
 222        addr[0] = 0xf0f0;       /* return to normal */
 223}
 224
 225static void flash_get_id_long( void *ptr,  short *ptr_manuf, short *ptr_dev_id)
 226{
 227        vu_short *addr = (vu_short*)ptr;
 228        vu_short *addr1, *addr2, *addr3;
 229
 230        addr1 = (vu_short*) ( ((int)ptr) + (0x5555<<2) );
 231        addr2 = (vu_short*) ( ((int)ptr) + (0x2AAA<<2) );
 232        addr3 = (vu_short*) ( ((int)ptr) + (0x5555<<2) );
 233
 234        *addr1 = 0xAAAA;
 235        *addr2 = 0x5555;
 236        *addr3 = 0x9090;
 237
 238        *ptr_manuf  = addr[0];
 239        *ptr_dev_id = addr[2];
 240
 241        addr[0] = 0xf0f0;       /* return to normal */
 242}
 243
 244static ulong flash_get_size ( short manu, short dev_id, flash_info_t *info)
 245{
 246        switch (manu) {
 247        case ((short)AMD_MANUFACT):
 248                info->flash_id = FLASH_MAN_AMD;
 249                break;
 250        case ((short)FUJ_MANUFACT):
 251                info->flash_id = FLASH_MAN_FUJ;
 252                break;
 253        case ((short)TOSH_MANUFACT):
 254                info->flash_id = FLASH_MAN_TOSH;
 255                break;
 256        default:
 257                info->flash_id = FLASH_UNKNOWN;
 258                info->sector_count = 0;
 259                info->size = 0;
 260                return (0);                     /* no or unknown flash  */
 261        }
 262
 263
 264        switch (dev_id) {
 265        case ((short)TOSH_ID_FVT160):
 266                info->flash_id += FLASH_AM160T;
 267                info->sector_count = 35;
 268                info->size = 0x00200000;
 269                break;                          /* => 1 MB              */
 270
 271        case ((short)TOSH_ID_FVB160):
 272                info->flash_id += FLASH_AM160B;
 273                info->sector_count = 35;
 274                info->size = 0x00200000;
 275                break;                          /* => 1 MB              */
 276
 277        case ((short)AMD_ID_LV400T):
 278                info->flash_id += FLASH_AM400T;
 279                info->sector_count = 11;
 280                info->size = 0x00100000;
 281                break;                          /* => 1 MB              */
 282
 283        case ((short)AMD_ID_LV400B):
 284                info->flash_id += FLASH_AM400B;
 285                info->sector_count = 11;
 286                info->size = 0x00100000;
 287                break;                          /* => 1 MB              */
 288
 289        case ((short)AMD_ID_LV800T):
 290                info->flash_id += FLASH_AM800T;
 291                info->sector_count = 19;
 292                info->size = 0x00200000;
 293                break;                          /* => 2 MB              */
 294
 295        case ((short)AMD_ID_LV800B):
 296                info->flash_id += FLASH_AM800B;
 297                info->sector_count = 19;
 298                info->size = 0x00400000;        /*%%% Size doubled by yooth */
 299                break;                          /* => 4 MB              */
 300
 301        case ((short)AMD_ID_LV160T):
 302                info->flash_id += FLASH_AM160T;
 303                info->sector_count = 35;
 304                info->size = 0x00200000;
 305                break;                          /* => 4 MB              */
 306
 307        case ((short)AMD_ID_LV160B):
 308                info->flash_id += FLASH_AM160B;
 309                info->sector_count = 35;
 310                info->size = 0x00200000;
 311                break;                          /* => 4 MB              */
 312        default:
 313                info->flash_id = FLASH_UNKNOWN;
 314                return (0);                     /* => no or unknown flash */
 315
 316        }
 317
 318        return(info->size);
 319}
 320
 321
 322/*-----------------------------------------------------------------------
 323 */
 324
 325int     flash_erase (flash_info_t *info, int s_first, int s_last)
 326{
 327        vu_short *addr = (vu_short*)(info->start[0]);
 328        int flag, prot, sect, l_sect;
 329        ulong start, now, last;
 330
 331        if ((s_first < 0) || (s_first > s_last)) {
 332                if (info->flash_id == FLASH_UNKNOWN) {
 333                        printf ("- missing\n");
 334                } else {
 335                        printf ("- no sectors to erase\n");
 336                }
 337                return 1;
 338        }
 339
 340        if ((info->flash_id == FLASH_UNKNOWN) ||
 341            (info->flash_id > FLASH_AMD_COMP)) {
 342                printf ("Can't erase unknown flash type %08lx - aborted\n",
 343                        info->flash_id);
 344                return 1;
 345        }
 346
 347        prot = 0;
 348        for (sect=s_first; sect<=s_last; ++sect) {
 349                if (info->protect[sect]) {
 350                        prot++;
 351                }
 352        }
 353
 354        if (prot) {
 355                printf ("- Warning: %d protected sectors will not be erased!\n",
 356                        prot);
 357        } else {
 358                printf ("\n");
 359        }
 360
 361        l_sect = -1;
 362
 363        /* Disable interrupts which might cause a timeout here */
 364        flag = disable_interrupts();
 365
 366        addr[0x555] = (vu_short)0xAAAAAAAA;
 367        addr[0xAAA] = (vu_short)0x55555555;
 368        addr[0x555] = (vu_short)0x80808080;
 369        addr[0x555] = (vu_short)0xAAAAAAAA;
 370        addr[0xAAA] = (vu_short)0x55555555;
 371
 372        /* Start erase on unprotected sectors */
 373        for (sect = s_first; sect<=s_last; sect++) {
 374                if (info->protect[sect] == 0) { /* not protected */
 375                        addr = (vu_short *)(info->start[sect]) ;
 376                        addr[0] = (vu_short)0x30303030 ;
 377                        l_sect = sect;
 378                }
 379        }
 380
 381        /* re-enable interrupts if necessary */
 382        if (flag)
 383                enable_interrupts();
 384
 385        /* wait at least 80us - let's wait 1 ms */
 386        udelay (1000);
 387
 388        /*
 389         * We wait for the last triggered sector
 390         */
 391        if (l_sect < 0)
 392                goto DONE;
 393
 394        start = get_timer (0);
 395        last  = start;
 396        addr = (vu_short *)(info->start[l_sect]);
 397        while ((addr[0] & 0x8080) != 0x8080) {
 398                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 399                        printf ("Timeout\n");
 400                        return 1;
 401                }
 402                /* show that we're waiting */
 403                if ((now - last) > 1000) {      /* every second */
 404                        putc ('.');
 405                        last = now;
 406                }
 407        }
 408
 409DONE:
 410        /* reset to read mode */
 411        addr = (vu_short *)info->start[0];
 412        addr[0] = (vu_short)0xF0F0F0F0; /* reset bank */
 413
 414        printf (" done\n");
 415        return 0;
 416}
 417
 418/*-----------------------------------------------------------------------
 419 * Copy memory to flash, returns:
 420 * 0 - OK
 421 * 1 - write timeout
 422 * 2 - Flash not erased
 423 */
 424
 425int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 426{
 427        ulong cp, wp, data;
 428        int i, l, rc;
 429
 430        wp = (addr & ~3);       /* get lower word aligned address */
 431
 432        /*
 433         * handle unaligned start bytes
 434         */
 435        if ((l = addr - wp) != 0) {
 436                data = 0;
 437                for (i=0, cp=wp; i<l; ++i, ++cp) {
 438                        data = (data << 8) | (*(uchar *)cp);
 439                }
 440                for (; i<4 && cnt>0; ++i) {
 441                        data = (data << 8) | *src++;
 442                        --cnt;
 443                        ++cp;
 444                }
 445                for (; cnt==0 && i<4; ++i, ++cp) {
 446                        data = (data << 8) | (*(uchar *)cp);
 447                }
 448
 449                if ((rc = write_word(info, wp, data)) != 0) {
 450                        return (rc);
 451                }
 452                wp += 4;
 453        }
 454
 455        /*
 456         * handle word aligned part
 457         */
 458        while (cnt >= 4) {
 459                data = 0;
 460                for (i=0; i<4; ++i) {
 461                        data = (data << 8) | *src++;
 462                }
 463                if ((rc = write_word(info, wp, data)) != 0) {
 464                        return (rc);
 465                }
 466                wp  += 4;
 467                cnt -= 4;
 468        }
 469
 470        if (cnt == 0) {
 471                return (0);
 472        }
 473
 474        /*
 475         * handle unaligned tail bytes
 476         */
 477        data = 0;
 478        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 479                data = (data << 8) | *src++;
 480                --cnt;
 481        }
 482        for (; i<4; ++i, ++cp) {
 483                data = (data << 8) | (*(uchar *)cp);
 484        }
 485
 486        return (write_word(info, wp, data));
 487}
 488
 489/*-----------------------------------------------------------------------
 490 * Write a word to Flash, returns:
 491 * 0 - OK
 492 * 1 - write timeout
 493 * 2 - Flash not erased
 494 */
 495static int write_word (flash_info_t *info, ulong dest, ulong data)
 496{
 497        vu_short *addr = (vu_short *)(info->start[0]);
 498        vu_short sdata;
 499
 500        ulong start;
 501        int flag;
 502
 503        /* Check if Flash is (sufficiently) erased */
 504        if ((*((vu_long *)dest) & data) != data) {
 505                return (2);
 506        }
 507
 508        /* First write upper 16 bits */
 509        sdata = (short)(data>>16);
 510
 511        /* Disable interrupts which might cause a timeout here */
 512        flag = disable_interrupts();
 513
 514        addr[0x555] = 0xAAAA;
 515        addr[0xAAA] = 0x5555;
 516        addr[0x555] = 0xA0A0;
 517
 518        *((vu_short *)dest) = sdata;
 519
 520        /* re-enable interrupts if necessary */
 521        if (flag)
 522                enable_interrupts();
 523
 524        /* data polling for D7 */
 525        start = get_timer (0);
 526        while ((*((vu_short *)dest) & 0x8080) != (sdata & 0x8080)) {
 527                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 528                        return (1);
 529                }
 530        }
 531
 532        /* Now write lower 16 bits */
 533        sdata = (short)(data&0xffff);
 534
 535        /* Disable interrupts which might cause a timeout here */
 536        flag = disable_interrupts();
 537
 538        addr[0x555] = 0xAAAA;
 539        addr[0xAAA] = 0x5555;
 540        addr[0x555] = 0xA0A0;
 541
 542        *((vu_short *)dest + 1) = sdata;
 543
 544        /* re-enable interrupts if necessary */
 545        if (flag)
 546                enable_interrupts();
 547
 548        /* data polling for D7 */
 549        start = get_timer (0);
 550        while ((*((vu_short *)dest + 1) & 0x8080) != (sdata & 0x8080)) {
 551                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 552                        return (1);
 553                }
 554        }
 555        return (0);
 556}
 557
 558/*-----------------------------------------------------------------------
 559 */
 560