uboot/board/cu824/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   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 <mpc824x.h>
  26#include <asm/processor.h>
  27
  28#if defined(CONFIG_ENV_IS_IN_FLASH)
  29# ifndef  CONFIG_ENV_ADDR
  30#  define CONFIG_ENV_ADDR       (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
  31# endif
  32# ifndef  CONFIG_ENV_SIZE
  33#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
  34# endif
  35# ifndef  CONFIG_ENV_SECT_SIZE
  36#  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
  37# endif
  38#endif
  39
  40#define FLASH_BANK_SIZE 0x800000
  41#define MAIN_SECT_SIZE  0x40000
  42#define PARAM_SECT_SIZE 0x8000
  43
  44#define BOARD_CTRL_REG 0xFE800013
  45
  46flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  47
  48static int write_data (flash_info_t *info, ulong dest, ulong *data);
  49static void write_via_fpu(vu_long *addr, ulong *data);
  50static __inline__ unsigned long get_msr(void);
  51static __inline__ void set_msr(unsigned long msr);
  52
  53/*---------------------------------------------------------------------*/
  54#undef  DEBUG_FLASH
  55
  56/*---------------------------------------------------------------------*/
  57#ifdef DEBUG_FLASH
  58#define DEBUGF(fmt,args...) printf(fmt ,##args)
  59#else
  60#define DEBUGF(fmt,args...)
  61#endif
  62/*---------------------------------------------------------------------*/
  63
  64/*-----------------------------------------------------------------------
  65 */
  66
  67unsigned long flash_init(void)
  68{
  69    int i, j;
  70    ulong size = 0;
  71    volatile unsigned char *bcr = (volatile unsigned char *)(BOARD_CTRL_REG);
  72
  73    DEBUGF("Write protect was: 0x%02X\n", *bcr);
  74    *bcr &= 0x1;        /* FWPT must be 0  */
  75    *bcr |= 0x6;        /* FWP0 = FWP1 = 1 */
  76    DEBUGF("Write protect is:  0x%02X\n", *bcr);
  77
  78    for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  79        vu_long *addr = (vu_long *)(CONFIG_SYS_FLASH_BASE + i * FLASH_BANK_SIZE);
  80
  81        addr[0] = 0x00900090;
  82
  83        DEBUGF ("Flash bank # %d:\n"
  84                "\tManuf. ID @ 0x%08lX: 0x%08lX\n"
  85                "\tDevice ID @ 0x%08lX: 0x%08lX\n",
  86                i,
  87                (ulong)(&addr[0]), addr[0],
  88                (ulong)(&addr[2]), addr[2]);
  89
  90        if ((addr[0] == addr[1]) && (addr[0] == INTEL_MANUFACT) &&
  91            (addr[2] == addr[3]) && (addr[2] == INTEL_ID_28F160F3B))
  92        {
  93            flash_info[i].flash_id = (FLASH_MAN_INTEL & FLASH_VENDMASK) |
  94                                     (INTEL_ID_28F160F3B & FLASH_TYPEMASK);
  95        } else {
  96            flash_info[i].flash_id = FLASH_UNKNOWN;
  97            addr[0] = 0xFFFFFFFF;
  98            goto Done;
  99        }
 100
 101        DEBUGF ("flash_id = 0x%08lX\n", flash_info[i].flash_id);
 102
 103        addr[0] = 0xFFFFFFFF;
 104
 105        flash_info[i].size = FLASH_BANK_SIZE;
 106        flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 107        memset(flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
 108        for (j = 0; j < flash_info[i].sector_count; j++) {
 109                if (j <= 7) {
 110                        flash_info[i].start[j] = CONFIG_SYS_FLASH_BASE +
 111                                                 i * FLASH_BANK_SIZE +
 112                                                 j * PARAM_SECT_SIZE;
 113                } else {
 114                        flash_info[i].start[j] = CONFIG_SYS_FLASH_BASE +
 115                                                 i * FLASH_BANK_SIZE +
 116                                                 (j - 7)*MAIN_SECT_SIZE;
 117                }
 118        }
 119        size += flash_info[i].size;
 120    }
 121
 122    /* Protect monitor and environment sectors
 123     */
 124#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
 125#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE + FLASH_BANK_SIZE
 126    flash_protect(FLAG_PROTECT_SET,
 127              CONFIG_SYS_MONITOR_BASE,
 128              CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
 129              &flash_info[1]);
 130#else
 131    flash_protect(FLAG_PROTECT_SET,
 132              CONFIG_SYS_MONITOR_BASE,
 133              CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
 134              &flash_info[0]);
 135#endif
 136#endif
 137
 138#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
 139#if CONFIG_ENV_ADDR >= CONFIG_SYS_FLASH_BASE + FLASH_BANK_SIZE
 140    flash_protect(FLAG_PROTECT_SET,
 141              CONFIG_ENV_ADDR,
 142              CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
 143              &flash_info[1]);
 144#else
 145    flash_protect(FLAG_PROTECT_SET,
 146              CONFIG_ENV_ADDR,
 147              CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
 148              &flash_info[0]);
 149#endif
 150#endif
 151
 152Done:
 153    return size;
 154}
 155
 156/*-----------------------------------------------------------------------
 157 */
 158void flash_print_info (flash_info_t * info)
 159{
 160        int i;
 161
 162        switch ((i = info->flash_id & FLASH_VENDMASK)) {
 163        case (FLASH_MAN_INTEL & FLASH_VENDMASK):
 164                printf ("Intel: ");
 165                break;
 166        default:
 167                printf ("Unknown Vendor 0x%04x ", i);
 168                break;
 169        }
 170
 171        switch ((i = info->flash_id & FLASH_TYPEMASK)) {
 172        case (INTEL_ID_28F160F3B & FLASH_TYPEMASK):
 173                printf ("28F160F3B (16Mbit)\n");
 174                break;
 175        default:
 176                printf ("Unknown Chip Type 0x%04x\n", i);
 177                goto Done;
 178                break;
 179        }
 180
 181        printf ("  Size: %ld MB in %d Sectors\n",
 182                        info->size >> 20, info->sector_count);
 183
 184        printf ("  Sector Start Addresses:");
 185        for (i = 0; i < info->sector_count; i++) {
 186                if ((i % 5) == 0) {
 187                        printf ("\n   ");
 188                }
 189                printf (" %08lX%s", info->start[i],
 190                                info->protect[i] ? " (RO)" : "     ");
 191        }
 192        printf ("\n");
 193
 194Done:
 195        return;
 196}
 197
 198/*-----------------------------------------------------------------------
 199 */
 200
 201int     flash_erase (flash_info_t *info, int s_first, int s_last)
 202{
 203        int flag, prot, sect;
 204        ulong start, now, last;
 205
 206        DEBUGF ("Erase flash bank %d sect %d ... %d\n",
 207                info - &flash_info[0], s_first, s_last);
 208
 209        if ((s_first < 0) || (s_first > s_last)) {
 210                if (info->flash_id == FLASH_UNKNOWN) {
 211                        printf ("- missing\n");
 212                } else {
 213                        printf ("- no sectors to erase\n");
 214                }
 215                return 1;
 216        }
 217
 218        if ((info->flash_id & FLASH_VENDMASK) !=
 219            (FLASH_MAN_INTEL & FLASH_VENDMASK)) {
 220                printf ("Can erase only Intel flash types - aborted\n");
 221                return 1;
 222        }
 223
 224        prot = 0;
 225        for (sect=s_first; sect<=s_last; ++sect) {
 226                if (info->protect[sect]) {
 227                        prot++;
 228                }
 229        }
 230
 231        if (prot) {
 232                printf ("- Warning: %d protected sectors will not be erased!\n",
 233                        prot);
 234        } else {
 235                printf ("\n");
 236        }
 237
 238        start = get_timer (0);
 239        last  = start;
 240        /* Start erase on unprotected sectors */
 241        for (sect = s_first; sect<=s_last; sect++) {
 242                if (info->protect[sect] == 0) { /* not protected */
 243                        vu_long *addr = (vu_long *)(info->start[sect]);
 244
 245                        DEBUGF ("Erase sect %d @ 0x%08lX\n",
 246                                sect, (ulong)addr);
 247
 248                        /* Disable interrupts which might cause a timeout
 249                         * here.
 250                         */
 251                        flag = disable_interrupts();
 252
 253                        addr[0] = 0x00500050;   /* clear status register */
 254                        addr[0] = 0x00200020;   /* erase setup */
 255                        addr[0] = 0x00D000D0;   /* erase confirm */
 256
 257                        addr[1] = 0x00500050;   /* clear status register */
 258                        addr[1] = 0x00200020;   /* erase setup */
 259                        addr[1] = 0x00D000D0;   /* erase confirm */
 260
 261                        /* re-enable interrupts if necessary */
 262                        if (flag)
 263                                enable_interrupts();
 264
 265                        /* wait at least 80us - let's wait 1 ms */
 266                        udelay (1000);
 267
 268                        while (((addr[0] & 0x00800080) != 0x00800080) ||
 269                               ((addr[1] & 0x00800080) != 0x00800080) ) {
 270                                if ((now=get_timer(start)) >
 271                                           CONFIG_SYS_FLASH_ERASE_TOUT) {
 272                                        printf ("Timeout\n");
 273                                        addr[0] = 0x00B000B0; /* suspend erase */
 274                                        addr[0] = 0x00FF00FF; /* to read mode  */
 275                                        return 1;
 276                                }
 277
 278                                /* show that we're waiting */
 279                                if ((now - last) > 1000) {  /* every second  */
 280                                        putc ('.');
 281                                        last = now;
 282                                }
 283                        }
 284
 285                        addr[0] = 0x00FF00FF;
 286                }
 287        }
 288        printf (" done\n");
 289        return 0;
 290}
 291
 292/*-----------------------------------------------------------------------
 293 * Copy memory to flash, returns:
 294 * 0 - OK
 295 * 1 - write timeout
 296 * 2 - Flash not erased
 297 * 4 - Flash not identified
 298 */
 299
 300#define FLASH_WIDTH     8       /* flash bus width in bytes */
 301
 302int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 303{
 304        ulong wp, cp, msr;
 305        int l, rc, i;
 306        ulong data[2];
 307        ulong *datah = &data[0];
 308        ulong *datal = &data[1];
 309
 310        DEBUGF ("Flash write_buff: @ 0x%08lx, src 0x%08lx len %ld\n",
 311                addr, (ulong)src, cnt);
 312
 313        if (info->flash_id == FLASH_UNKNOWN) {
 314                return 4;
 315        }
 316
 317        msr = get_msr();
 318        set_msr(msr | MSR_FP);
 319
 320        wp = (addr & ~(FLASH_WIDTH-1)); /* get lower aligned address */
 321
 322        /*
 323         * handle unaligned start bytes
 324         */
 325        if ((l = addr - wp) != 0) {
 326                *datah = *datal = 0;
 327
 328                for (i = 0, cp = wp; i < l; i++, cp++) {
 329                        if (i >= 4) {
 330                                *datah = (*datah << 8) |
 331                                                ((*datal & 0xFF000000) >> 24);
 332                        }
 333
 334                        *datal = (*datal << 8) | (*(uchar *)cp);
 335                }
 336                for (; i < FLASH_WIDTH && cnt > 0; ++i) {
 337                        char tmp;
 338
 339                        tmp = *src;
 340
 341                        src++;
 342
 343                        if (i >= 4) {
 344                                *datah = (*datah << 8) |
 345                                                ((*datal & 0xFF000000) >> 24);
 346                        }
 347
 348                        *datal = (*datal << 8) | tmp;
 349
 350                        --cnt; ++cp;
 351                }
 352
 353                for (; cnt == 0 && i < FLASH_WIDTH; ++i, ++cp) {
 354                        if (i >= 4) {
 355                                *datah = (*datah << 8) |
 356                                                ((*datal & 0xFF000000) >> 24);
 357                        }
 358
 359                        *datal = (*datah << 8) | (*(uchar *)cp);
 360                }
 361
 362                if ((rc = write_data(info, wp, data)) != 0) {
 363                        set_msr(msr);
 364                        return (rc);
 365                }
 366
 367                wp += FLASH_WIDTH;
 368        }
 369
 370        /*
 371         * handle FLASH_WIDTH aligned part
 372         */
 373        while (cnt >= FLASH_WIDTH) {
 374                *datah = *(ulong *)src;
 375                *datal = *(ulong *)(src + 4);
 376                if ((rc = write_data(info, wp, data)) != 0) {
 377                        set_msr(msr);
 378                        return (rc);
 379                }
 380                wp  += FLASH_WIDTH;
 381                cnt -= FLASH_WIDTH;
 382                src += FLASH_WIDTH;
 383        }
 384
 385        if (cnt == 0) {
 386                set_msr(msr);
 387                return (0);
 388        }
 389
 390        /*
 391         * handle unaligned tail bytes
 392         */
 393        *datah = *datal = 0;
 394        for (i = 0, cp = wp; i < FLASH_WIDTH && cnt > 0; ++i, ++cp) {
 395                char tmp;
 396
 397                tmp = *src;
 398
 399                src++;
 400
 401                if (i >= 4) {
 402                        *datah = (*datah << 8) | ((*datal & 0xFF000000) >> 24);
 403                }
 404
 405                *datal = (*datal << 8) | tmp;
 406
 407                --cnt;
 408        }
 409
 410        for (; i < FLASH_WIDTH; ++i, ++cp) {
 411                if (i >= 4) {
 412                        *datah = (*datah << 8) | ((*datal & 0xFF000000) >> 24);
 413                }
 414
 415                *datal = (*datal << 8) | (*(uchar *)cp);
 416        }
 417
 418        rc = write_data(info, wp, data);
 419        set_msr(msr);
 420
 421        return (rc);
 422}
 423
 424/*-----------------------------------------------------------------------
 425 * Write a word to Flash, returns:
 426 * 0 - OK
 427 * 1 - write timeout
 428 * 2 - Flash not erased
 429 */
 430static int write_data (flash_info_t *info, ulong dest, ulong *data)
 431{
 432        vu_long *addr = (vu_long *)dest;
 433        ulong start;
 434        int flag;
 435
 436        /* Check if Flash is (sufficiently) erased */
 437        if (((addr[0] & data[0]) != data[0]) ||
 438            ((addr[1] & data[1]) != data[1]) ) {
 439                return (2);
 440        }
 441        /* Disable interrupts which might cause a timeout here */
 442        flag = disable_interrupts();
 443
 444        addr[0] = 0x00400040;           /* write setup */
 445        write_via_fpu(addr, data);
 446
 447        /* re-enable interrupts if necessary */
 448        if (flag)
 449                enable_interrupts();
 450
 451        start = get_timer (0);
 452
 453        while (((addr[0] & 0x00800080) != 0x00800080) ||
 454               ((addr[1] & 0x00800080) != 0x00800080) ) {
 455                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 456                        addr[0] = 0x00FF00FF;   /* restore read mode */
 457                        return (1);
 458                }
 459        }
 460
 461        addr[0] = 0x00FF00FF;   /* restore read mode */
 462
 463        return (0);
 464}
 465
 466/*-----------------------------------------------------------------------
 467 */
 468static void write_via_fpu(vu_long *addr, ulong *data)
 469{
 470        __asm__ __volatile__ ("lfd  1, 0(%0)" : : "r" (data));
 471        __asm__ __volatile__ ("stfd 1, 0(%0)" : : "r" (addr));
 472}
 473/*-----------------------------------------------------------------------
 474 */
 475static __inline__ unsigned long get_msr(void)
 476{
 477    unsigned long msr;
 478
 479    __asm__ __volatile__ ("mfmsr %0" : "=r" (msr) :);
 480    return msr;
 481}
 482
 483static __inline__ void set_msr(unsigned long msr)
 484{
 485    __asm__ __volatile__ ("mtmsr %0" : : "r" (msr));
 486}
 487