uboot/board/freescale/mpc8266ads/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000, 2001
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * (C) Copyright 2001, Stuart Hughes, Lineo Inc, stuarth@lineo.com
   6 * Add support the Sharp chips on the mpc8260ads.
   7 * I started with board/ip860/flash.c and made changes I found in
   8 * the MTD project by David Schleef.
   9 *
  10 * See file CREDITS for list of people who contributed to this
  11 * project.
  12 *
  13 * This program is free software; you can redistribute it and/or
  14 * modify it under the terms of the GNU General Public License as
  15 * published by the Free Software Foundation; either version 2 of
  16 * the License, or (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  26 * MA 02111-1307 USA
  27 */
  28
  29#include <common.h>
  30
  31
  32flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  33
  34#if defined(CONFIG_ENV_IS_IN_FLASH)
  35# ifndef  CONFIG_ENV_ADDR
  36#  define CONFIG_ENV_ADDR       (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
  37# endif
  38# ifndef  CONFIG_ENV_SIZE
  39#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
  40# endif
  41# ifndef  CONFIG_ENV_SECT_SIZE
  42#  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
  43# endif
  44#endif
  45
  46/*-----------------------------------------------------------------------
  47 * Functions
  48 */
  49static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  50static int write_word (flash_info_t *info, ulong dest, ulong data);
  51static int clear_block_lock_bit(vu_long * addr);
  52
  53/*-----------------------------------------------------------------------
  54 */
  55
  56unsigned long flash_init (void)
  57{
  58#ifndef CONFIG_MPC8266ADS
  59        volatile immap_t        *immap  = (immap_t *)CONFIG_SYS_IMMR;
  60        volatile memctl8xx_t    *memctl = &immap->im_memctl;
  61        volatile ip860_bcsr_t   *bcsr   = (ip860_bcsr_t *)BCSR_BASE;
  62#endif
  63        unsigned long size;
  64        int i;
  65
  66        /* Init: enable write,
  67         * or we cannot even write flash commands
  68         */
  69#ifndef CONFIG_MPC8266ADS
  70        bcsr->bd_ctrl |= BD_CTRL_FLWE;
  71#endif
  72
  73
  74        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  75                flash_info[i].flash_id = FLASH_UNKNOWN;
  76
  77                /* set the default sector offset */
  78        }
  79
  80        /* Static FLASH Bank configuration here - FIXME XXX */
  81
  82        size = flash_get_size((vu_long *)FLASH_BASE, &flash_info[0]);
  83
  84        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
  85                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
  86                        size, size<<20);
  87        }
  88
  89#ifndef CONFIG_MPC8266ADS
  90        /* Remap FLASH according to real size */
  91        memctl->memc_or1 = CONFIG_SYS_OR_TIMING_FLASH | (-size & 0xFFFF8000);
  92        memctl->memc_br1 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) |
  93                                (memctl->memc_br1 & ~(BR_BA_MSK));
  94#endif
  95        /* Re-do sizing to get full correct info */
  96        size = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  97
  98        flash_info[0].size = size;
  99
 100#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
 101        /* monitor protection ON by default */
 102        flash_protect(FLAG_PROTECT_SET,
 103                      CONFIG_SYS_MONITOR_BASE,
 104                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
 105                      &flash_info[0]);
 106#endif
 107
 108#ifdef  CONFIG_ENV_IS_IN_FLASH
 109        /* ENV protection ON by default */
 110        flash_protect(FLAG_PROTECT_SET,
 111                      CONFIG_ENV_ADDR,
 112                      CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
 113                      &flash_info[0]);
 114#endif
 115        return (size);
 116}
 117
 118/*-----------------------------------------------------------------------
 119 */
 120void flash_print_info  (flash_info_t *info)
 121{
 122        int i;
 123
 124        if (info->flash_id == FLASH_UNKNOWN) {
 125                printf ("missing or unknown FLASH type\n");
 126                return;
 127        }
 128
 129        switch (info->flash_id & FLASH_VENDMASK) {
 130        case FLASH_MAN_INTEL:   printf ("Intel ");              break;
 131        case FLASH_MAN_SHARP:   printf ("Sharp ");              break;
 132        default:                printf ("Unknown Vendor ");     break;
 133        }
 134
 135        switch (info->flash_id & FLASH_TYPEMASK) {
 136        case FLASH_28F016SV:    printf ("28F016SV (16 Mbit, 32 x 64k)\n");
 137                                break;
 138        case FLASH_28F160S3:    printf ("28F160S3 (16 Mbit, 32 x 512K)\n");
 139                                break;
 140        case FLASH_28F320S3:    printf ("28F320S3 (32 Mbit, 64 x 512K)\n");
 141                                break;
 142        case FLASH_LH28F016SCT: printf ("28F016SC (16 Mbit, 32 x 64K)\n");
 143                                break;
 144        default:                printf ("Unknown Chip Type\n");
 145                                break;
 146        }
 147
 148        printf ("  Size: %ld MB in %d Sectors\n",
 149                info->size >> 20, info->sector_count);
 150
 151        printf ("  Sector Start Addresses:");
 152        for (i=0; i<info->sector_count; ++i) {
 153                if ((i % 5) == 0)
 154                        printf ("\n   ");
 155                printf (" %08lX%s",
 156                        info->start[i],
 157                        info->protect[i] ? " (RO)" : "     "
 158                );
 159        }
 160        printf ("\n");
 161}
 162
 163/*-----------------------------------------------------------------------
 164 */
 165
 166
 167/*-----------------------------------------------------------------------
 168 */
 169
 170/*
 171 * The following code cannot be run from FLASH!
 172 */
 173
 174static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 175{
 176        short i;
 177        ulong value;
 178        ulong base = (ulong)addr;
 179        ulong sector_offset;
 180
 181        /* Write "Intelligent Identifier" command: read Manufacturer ID */
 182        *addr = 0x90909090;
 183
 184        value = addr[0] & 0x00FF00FF;
 185        switch (value) {
 186        case MT_MANUFACT:       /* SHARP, MT or => Intel */
 187        case INTEL_ALT_MANU:
 188                info->flash_id = FLASH_MAN_INTEL;
 189                break;
 190        default:
 191                printf("unknown manufacturer: %x\n", (unsigned int)value);
 192                info->flash_id = FLASH_UNKNOWN;
 193                info->sector_count = 0;
 194                info->size = 0;
 195                return (0);                     /* no or unknown flash  */
 196        }
 197
 198        value = addr[1];                        /* device ID            */
 199
 200        switch (value) {
 201        case (INTEL_ID_28F016S):
 202                info->flash_id += FLASH_28F016SV;
 203                info->sector_count = 32;
 204                info->size = 0x00400000;
 205                sector_offset = 0x20000;
 206                break;                          /* => 2x2 MB            */
 207
 208        case (INTEL_ID_28F160S3):
 209                info->flash_id += FLASH_28F160S3;
 210                info->sector_count = 32;
 211                info->size = 0x00400000;
 212                sector_offset = 0x20000;
 213                break;                          /* => 2x2 MB            */
 214
 215        case (INTEL_ID_28F320S3):
 216                info->flash_id += FLASH_28F320S3;
 217                info->sector_count = 64;
 218                info->size = 0x00800000;
 219                sector_offset = 0x20000;
 220                break;                          /* => 2x4 MB            */
 221
 222        case SHARP_ID_28F016SCL:
 223        case SHARP_ID_28F016SCZ:
 224                info->flash_id      = FLASH_MAN_SHARP | FLASH_LH28F016SCT;
 225                info->sector_count  = 32;
 226                info->size          = 0x00800000;
 227                sector_offset = 0x40000;
 228                break;                          /* => 4x2 MB            */
 229
 230
 231        default:
 232                info->flash_id = FLASH_UNKNOWN;
 233                return (0);                     /* => no or unknown flash */
 234
 235        }
 236
 237        /* set up sector start address table */
 238        for (i = 0; i < info->sector_count; i++) {
 239                info->start[i] = base;
 240                base += sector_offset;
 241                /* don't know how to check sector protection */
 242                info->protect[i] = 0;
 243        }
 244
 245        /*
 246         * Prevent writes to uninitialized FLASH.
 247         */
 248        if (info->flash_id != FLASH_UNKNOWN) {
 249                addr = (vu_long *)info->start[0];
 250
 251                *addr = 0xFFFFFF;       /* reset bank to read array mode */
 252        }
 253
 254        return (info->size);
 255}
 256
 257
 258/*-----------------------------------------------------------------------
 259 */
 260
 261int     flash_erase (flash_info_t *info, int s_first, int s_last)
 262{
 263        int flag, prot, sect;
 264        ulong start, now, last;
 265
 266        if ((s_first < 0) || (s_first > s_last)) {
 267                if (info->flash_id == FLASH_UNKNOWN) {
 268                        printf ("- missing\n");
 269                } else {
 270                        printf ("- no sectors to erase\n");
 271                }
 272                return 1;
 273        }
 274
 275        if (    ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL)
 276             && ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_SHARP) ) {
 277                printf ("Can't erase unknown flash type %08lx - aborted\n",
 278                        info->flash_id);
 279                return 1;
 280        }
 281
 282        prot = 0;
 283        for (sect=s_first; sect<=s_last; ++sect) {
 284                if (info->protect[sect]) {
 285                        prot++;
 286                }
 287        }
 288
 289        if (prot) {
 290                printf ("- Warning: %d protected sectors will not be erased!\n",
 291                        prot);
 292        } else {
 293                printf ("\n");
 294        }
 295
 296        /* Make Sure Block Lock Bit is not set. */
 297        if(clear_block_lock_bit((vu_long *)(info->start[s_first]))){
 298                return 1;
 299        }
 300
 301
 302        /* Start erase on unprotected sectors */
 303        for (sect = s_first; sect<=s_last; sect++) {
 304                if (info->protect[sect] == 0) { /* not protected */
 305                        vu_long *addr = (vu_long *)(info->start[sect]);
 306
 307                        last = start = get_timer (0);
 308
 309                        /* Disable interrupts which might cause a timeout here */
 310                        flag = disable_interrupts();
 311
 312                        /* Reset Array */
 313                        *addr = 0xffffffff;
 314                        /* Clear Status Register */
 315                        *addr = 0x50505050;
 316                        /* Single Block Erase Command */
 317                        *addr = 0x20202020;
 318                        /* Confirm */
 319                        *addr = 0xD0D0D0D0;
 320
 321                        if((info->flash_id & FLASH_TYPEMASK) != FLASH_LH28F016SCT) {
 322                            /* Resume Command, as per errata update */
 323                            *addr = 0xD0D0D0D0;
 324                        }
 325
 326                        /* re-enable interrupts if necessary */
 327                        if (flag)
 328                                enable_interrupts();
 329
 330                        /* wait at least 80us - let's wait 1 ms */
 331                        udelay (1000);
 332                        while ((*addr & 0x80808080) != 0x80808080) {
 333                                if(*addr & 0x20202020){
 334                                        printf("Error in Block Erase - Lock Bit may be set!\n");
 335                                        printf("Status Register = 0x%X\n", (uint)*addr);
 336                                        *addr = 0xFFFFFFFF;     /* reset bank */
 337                                        return 1;
 338                                }
 339                                if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 340                                        printf ("Timeout\n");
 341                                        *addr = 0xFFFFFFFF;     /* reset bank */
 342                                        return 1;
 343                                }
 344                                /* show that we're waiting */
 345                                if ((now - last) > 1000) {      /* every second */
 346                                        putc ('.');
 347                                        last = now;
 348                                }
 349                        }
 350
 351                        /* reset to read mode */
 352                        *addr = 0xFFFFFFFF;
 353                }
 354        }
 355
 356        printf (" done\n");
 357        return 0;
 358}
 359
 360/*-----------------------------------------------------------------------
 361 * Copy memory to flash, returns:
 362 * 0 - OK
 363 * 1 - write timeout
 364 * 2 - Flash not erased
 365 */
 366
 367int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 368{
 369        ulong cp, wp, data;
 370        int i, l, rc;
 371
 372        wp = (addr & ~3);       /* get lower word aligned address */
 373
 374        /*
 375         * handle unaligned start bytes
 376         */
 377        if ((l = addr - wp) != 0) {
 378                data = 0;
 379                for (i=0, cp=wp; i<l; ++i, ++cp) {
 380                        data = (data << 8) | (*(uchar *)cp);
 381                }
 382                for (; i<4 && cnt>0; ++i) {
 383                        data = (data << 8) | *src++;
 384                        --cnt;
 385                        ++cp;
 386                }
 387                for (; cnt==0 && i<4; ++i, ++cp) {
 388                        data = (data << 8) | (*(uchar *)cp);
 389                }
 390
 391                if ((rc = write_word(info, wp, data)) != 0) {
 392                        return (rc);
 393                }
 394                wp += 4;
 395        }
 396
 397        /*
 398         * handle word aligned part
 399         */
 400        while (cnt >= 4) {
 401                data = 0;
 402                for (i=0; i<4; ++i) {
 403                        data = (data << 8) | *src++;
 404                }
 405                if ((rc = write_word(info, wp, data)) != 0) {
 406                        return (rc);
 407                }
 408                wp  += 4;
 409                cnt -= 4;
 410        }
 411
 412        if (cnt == 0) {
 413                return (0);
 414        }
 415
 416        /*
 417         * handle unaligned tail bytes
 418         */
 419        data = 0;
 420        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 421                data = (data << 8) | *src++;
 422                --cnt;
 423        }
 424        for (; i<4; ++i, ++cp) {
 425                data = (data << 8) | (*(uchar *)cp);
 426        }
 427
 428        return (write_word(info, wp, data));
 429}
 430
 431/*-----------------------------------------------------------------------
 432 * Write a word to Flash, returns:
 433 * 0 - OK
 434 * 1 - write timeout
 435 * 2 - Flash not erased
 436 */
 437static int write_word (flash_info_t *info, ulong dest, ulong data)
 438{
 439        vu_long *addr = (vu_long *)dest;
 440        ulong start, csr;
 441        int flag;
 442
 443        /* Check if Flash is (sufficiently) erased */
 444        if ((*addr & data) != data) {
 445                return (2);
 446        }
 447        /* Disable interrupts which might cause a timeout here */
 448        flag = disable_interrupts();
 449
 450        /* Write Command */
 451        *addr = 0x10101010;
 452
 453        /* Write Data */
 454        *addr = data;
 455
 456        /* re-enable interrupts if necessary */
 457        if (flag)
 458                enable_interrupts();
 459
 460        /* data polling for D7 */
 461        start = get_timer (0);
 462        flag  = 0;
 463        while (((csr = *addr) & 0x80808080) != 0x80808080) {
 464                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 465                        flag = 1;
 466                        break;
 467                }
 468        }
 469        if (csr & 0x40404040) {
 470                printf ("CSR indicates write error (%08lx) at %08lx\n", csr, (ulong)addr);
 471                flag = 1;
 472        }
 473
 474        /* Clear Status Registers Command */
 475        *addr = 0x50505050;
 476        /* Reset to read array mode */
 477        *addr = 0xFFFFFFFF;
 478
 479        return (flag);
 480}
 481
 482/*-----------------------------------------------------------------------
 483 * Clear Block Lock Bit, returns:
 484 * 0 - OK
 485 * 1 - Timeout
 486 */
 487
 488static int clear_block_lock_bit(vu_long  * addr)
 489{
 490        ulong start, now;
 491
 492        /* Reset Array */
 493        *addr = 0xffffffff;
 494        /* Clear Status Register */
 495        *addr = 0x50505050;
 496
 497        *addr = 0x60606060;
 498        *addr = 0xd0d0d0d0;
 499
 500        start = get_timer (0);
 501        while(*addr != 0x80808080){
 502                if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 503                        printf ("Timeout on clearing Block Lock Bit\n");
 504                        *addr = 0xFFFFFFFF;     /* reset bank */
 505                        return 1;
 506                }
 507        }
 508        return 0;
 509}
 510