uboot/board/sl8245/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001 - 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 <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_SECT1_SIZE 0x20000
  43#define PARAM_SECT23_SIZE 0x8000
  44#define PARAM_SECT4_SIZE 0x10000
  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#define __align__ __attribute__ ((aligned (8)))
  65static __align__ ulong precmd0[2]   = { 0x00aa00aa, 0x00aa00aa };
  66static __align__ ulong precmd1[2]   = { 0x00550055, 0x00550055 };
  67static __align__ ulong cmdid[2]     = { 0x00900090, 0x00900090 };
  68static __align__ ulong cmderase[2]  = { 0x00800080, 0x00800080 };
  69static __align__ ulong cmdersusp[2] = { 0x00b000b0, 0x00b000b0 };
  70static __align__ ulong cmdsecter[2] = { 0x00300030, 0x00300030 };
  71static __align__ ulong cmdprog[2]   = { 0x00a000a0, 0x00a000a0 };
  72static __align__ ulong cmdres[2]    = { 0x00f000f0, 0x00f000f0 };
  73
  74/*-----------------------------------------------------------------------
  75 */
  76
  77unsigned long flash_init (void)
  78{
  79        int i, j;
  80        ulong size = 0;
  81
  82        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  83                vu_long *addr = (vu_long *) (CONFIG_SYS_FLASH_BASE + i * FLASH_BANK_SIZE);
  84
  85                write_via_fpu (&addr[0xaaa], precmd0);
  86                write_via_fpu (&addr[0x554], precmd1);
  87                write_via_fpu (&addr[0xaaa], cmdid);
  88
  89                DEBUGF ("Flash bank # %d:\n"
  90                        "\tManuf. ID @ 0x%08lX: 0x%08lX\n"
  91                        "\tDevice ID @ 0x%08lX: 0x%08lX\n",
  92                        i,
  93                        (ulong) (&addr[0]), addr[0],
  94                        (ulong) (&addr[2]), addr[2]);
  95
  96                if ((addr[0] == addr[1]) && (addr[0] == AMD_MANUFACT) &&
  97                        (addr[2] == addr[3]) && (addr[2] == AMD_ID_LV160T)) {
  98                        flash_info[i].flash_id = (FLASH_MAN_AMD & FLASH_VENDMASK) |
  99                                        (FLASH_AM160T & FLASH_TYPEMASK);
 100                } else {
 101                        flash_info[i].flash_id = FLASH_UNKNOWN;
 102                        write_via_fpu (addr, cmdres);
 103                        goto Done;
 104                }
 105
 106                DEBUGF ("flash_id = 0x%08lX\n", flash_info[i].flash_id);
 107
 108                write_via_fpu (addr, cmdres);
 109
 110                flash_info[i].size = FLASH_BANK_SIZE;
 111                flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 112                memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
 113                for (j = 0; j < 32; j++) {
 114                        flash_info[i].start[j] = CONFIG_SYS_FLASH_BASE +
 115                                        i * FLASH_BANK_SIZE + j * MAIN_SECT_SIZE;
 116                }
 117                flash_info[i].start[32] =
 118                                flash_info[i].start[31] + PARAM_SECT1_SIZE;
 119                flash_info[i].start[33] =
 120                                flash_info[i].start[32] + PARAM_SECT23_SIZE;
 121                flash_info[i].start[34] =
 122                                flash_info[i].start[33] + PARAM_SECT23_SIZE;
 123                size += flash_info[i].size;
 124        }
 125
 126        /* Protect monitor and environment sectors
 127         */
 128#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
 129#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE + FLASH_BANK_SIZE
 130        flash_protect ( FLAG_PROTECT_SET,
 131                        CONFIG_SYS_MONITOR_BASE,
 132                        CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
 133                        &flash_info[1]);
 134#else
 135        flash_protect ( FLAG_PROTECT_SET,
 136                        CONFIG_SYS_MONITOR_BASE,
 137                        CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1,
 138                        &flash_info[0]);
 139#endif
 140#endif
 141
 142#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
 143#if CONFIG_ENV_ADDR >= CONFIG_SYS_FLASH_BASE + FLASH_BANK_SIZE
 144        flash_protect ( FLAG_PROTECT_SET,
 145                        CONFIG_ENV_ADDR,
 146                        CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[1]);
 147#else
 148        flash_protect ( FLAG_PROTECT_SET,
 149                        CONFIG_ENV_ADDR,
 150                        CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
 151#endif
 152#endif
 153
 154Done:
 155        return size;
 156}
 157
 158/*-----------------------------------------------------------------------
 159 */
 160void flash_print_info (flash_info_t * info)
 161{
 162        int i;
 163
 164        switch ((i = info->flash_id & FLASH_VENDMASK)) {
 165        case (FLASH_MAN_AMD & FLASH_VENDMASK):
 166                printf ("Intel: ");
 167                break;
 168        default:
 169                printf ("Unknown Vendor 0x%04x ", i);
 170                break;
 171        }
 172
 173        switch ((i = info->flash_id & FLASH_TYPEMASK)) {
 174        case (FLASH_AM160T & FLASH_TYPEMASK):
 175                printf ("AM29LV160BT (16Mbit)\n");
 176                break;
 177        default:
 178                printf ("Unknown Chip Type 0x%04x\n", i);
 179                goto Done;
 180                break;
 181        }
 182
 183        printf ("  Size: %ld MB in %d Sectors\n",
 184                        info->size >> 20, info->sector_count);
 185
 186        printf ("  Sector Start Addresses:");
 187        for (i = 0; i < info->sector_count; i++) {
 188                if ((i % 5) == 0) {
 189                        printf ("\n   ");
 190                }
 191                printf (" %08lX%s", info->start[i],
 192                        info->protect[i] ? " (RO)" : "     ");
 193        }
 194        printf ("\n");
 195
 196  Done:
 197        return;
 198}
 199
 200/*-----------------------------------------------------------------------
 201 */
 202
 203int flash_erase (flash_info_t * info, int s_first, int s_last)
 204{
 205        int flag, prot, sect;
 206        ulong start, now, last;
 207
 208        DEBUGF ("Erase flash bank %d sect %d ... %d\n",
 209                info - &flash_info[0], s_first, s_last);
 210
 211        if ((s_first < 0) || (s_first > s_last)) {
 212                if (info->flash_id == FLASH_UNKNOWN) {
 213                        printf ("- missing\n");
 214                } else {
 215                        printf ("- no sectors to erase\n");
 216                }
 217                return 1;
 218        }
 219
 220        if ((info->flash_id & FLASH_VENDMASK) !=
 221                (FLASH_MAN_AMD & FLASH_VENDMASK)) {
 222                printf ("Can erase only AMD flash types - aborted\n");
 223                return 1;
 224        }
 225
 226        prot = 0;
 227        for (sect = s_first; sect <= s_last; ++sect) {
 228                if (info->protect[sect]) {
 229                        prot++;
 230                }
 231        }
 232
 233        if (prot) {
 234                printf ("- Warning: %d protected sectors will not be erased!\n",
 235                        prot);
 236        } else {
 237                printf ("\n");
 238        }
 239
 240        start = get_timer (0);
 241        last = start;
 242        /* Start erase on unprotected sectors */
 243        for (sect = s_first; sect <= s_last; sect++) {
 244                if (info->protect[sect] == 0) { /* not protected */
 245                        vu_long *addr = (vu_long *) (info->start[sect]);
 246
 247                        DEBUGF ("Erase sect %d @ 0x%08lX\n", sect, (ulong) addr);
 248
 249                        /* Disable interrupts which might cause a timeout
 250                         * here.
 251                         */
 252                        flag = disable_interrupts ();
 253
 254                        write_via_fpu (&addr[0xaaa], precmd0);
 255                        write_via_fpu (&addr[0x554], precmd1);
 256                        write_via_fpu (&addr[0xaaa], cmderase);
 257                        write_via_fpu (&addr[0xaaa], precmd0);
 258                        write_via_fpu (&addr[0x554], precmd1);
 259                        write_via_fpu (&addr[0xaaa], cmdsecter);
 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)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 271                                        printf ("Timeout\n");
 272                                        write_via_fpu (addr, cmdersusp);
 273                                        write_via_fpu (addr, cmdres);
 274                                        return 1;
 275                                }
 276
 277                                /* show that we're waiting */
 278                                if ((now - last) > 1000) {      /* every second  */
 279                                        putc ('.');
 280                                        last = now;
 281                                }
 282                        }
 283
 284                        write_via_fpu (addr, cmdres);
 285                }
 286        }
 287        printf (" done\n");
 288        return 0;
 289}
 290
 291/*-----------------------------------------------------------------------
 292 * Copy memory to flash, returns:
 293 * 0 - OK
 294 * 1 - write timeout
 295 * 2 - Flash not erased
 296 * 4 - Flash not identified
 297 */
 298
 299#define FLASH_WIDTH     8               /* flash bus width in bytes */
 300
 301int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 302{
 303        ulong wp, cp, msr;
 304        int l, rc, i;
 305        ulong data[2];
 306        ulong *datah = &data[0];
 307        ulong *datal = &data[1];
 308
 309        DEBUGF ("Flash write_buff: @ 0x%08lx, src 0x%08lx len %ld\n",
 310                addr, (ulong) src, cnt);
 311
 312        if (info->flash_id == FLASH_UNKNOWN) {
 313                return 4;
 314        }
 315
 316        msr = get_msr ();
 317        set_msr (msr | MSR_FP);
 318
 319        wp = (addr & ~(FLASH_WIDTH - 1));       /* get lower aligned address */
 320
 321        /*
 322         * handle unaligned start bytes
 323         */
 324        if ((l = addr - wp) != 0) {
 325                *datah = *datal = 0;
 326
 327                for (i = 0, cp = wp; i < l; i++, cp++) {
 328                        if (i >= 4) {
 329                                *datah = (*datah << 8) | ((*datal & 0xFF000000) >> 24);
 330                        }
 331
 332                        *datal = (*datal << 8) | (*(uchar *) cp);
 333                }
 334                for (; i < FLASH_WIDTH && cnt > 0; ++i) {
 335                        char tmp;
 336
 337                        tmp = *src;
 338
 339                        src++;
 340
 341                        if (i >= 4) {
 342                                *datah = (*datah << 8) | ((*datal & 0xFF000000) >> 24);
 343                        }
 344
 345                        *datal = (*datal << 8) | tmp;
 346
 347                        --cnt;
 348                        ++cp;
 349                }
 350
 351                for (; cnt == 0 && i < FLASH_WIDTH; ++i, ++cp) {
 352                        if (i >= 4) {
 353                                *datah = (*datah << 8) | ((*datal & 0xFF000000) >> 24);
 354                        }
 355
 356                        *datal = (*datah << 8) | (*(uchar *) cp);
 357                }
 358
 359                if ((rc = write_data (info, wp, data)) != 0) {
 360                        set_msr (msr);
 361                        return (rc);
 362                }
 363
 364                wp += FLASH_WIDTH;
 365        }
 366
 367        /*
 368         * handle FLASH_WIDTH aligned part
 369         */
 370        while (cnt >= FLASH_WIDTH) {
 371                *datah = *(ulong *) src;
 372                *datal = *(ulong *) (src + 4);
 373                if ((rc = write_data (info, wp, data)) != 0) {
 374                        set_msr (msr);
 375                        return (rc);
 376                }
 377                wp += FLASH_WIDTH;
 378                cnt -= FLASH_WIDTH;
 379                src += FLASH_WIDTH;
 380        }
 381
 382        if (cnt == 0) {
 383                set_msr (msr);
 384                return (0);
 385        }
 386
 387        /*
 388         * handle unaligned tail bytes
 389         */
 390        *datah = *datal = 0;
 391        for (i = 0, cp = wp; i < FLASH_WIDTH && cnt > 0; ++i, ++cp) {
 392                char tmp;
 393
 394                tmp = *src;
 395
 396                src++;
 397
 398                if (i >= 4) {
 399                        *datah = (*datah << 8) | ((*datal & 0xFF000000) >> 24);
 400                }
 401
 402                *datal = (*datal << 8) | tmp;
 403
 404                --cnt;
 405        }
 406
 407        for (; i < FLASH_WIDTH; ++i, ++cp) {
 408                if (i >= 4) {
 409                        *datah = (*datah << 8) | ((*datal & 0xFF000000) >> 24);
 410                }
 411
 412                *datal = (*datal << 8) | (*(uchar *) cp);
 413        }
 414
 415        rc = write_data (info, wp, data);
 416        set_msr (msr);
 417
 418        return (rc);
 419}
 420
 421/*-----------------------------------------------------------------------
 422 * Write a word to Flash, returns:
 423 * 0 - OK
 424 * 1 - write timeout
 425 * 2 - Flash not erased
 426 */
 427static int write_data (flash_info_t * info, ulong dest, ulong * data)
 428{
 429        vu_long *chip = (vu_long *) (info->start[0]);
 430        vu_long *addr = (vu_long *) dest;
 431        ulong start;
 432        int flag;
 433
 434        /* Check if Flash is (sufficiently) erased */
 435        if (((addr[0] & data[0]) != data[0]) ||
 436                ((addr[1] & data[1]) != data[1])) {
 437                return (2);
 438        }
 439        /* Disable interrupts which might cause a timeout here */
 440        flag = disable_interrupts ();
 441
 442        write_via_fpu (&chip[0xaaa], precmd0);
 443        write_via_fpu (&chip[0x554], precmd1);
 444        write_via_fpu (&chip[0xaaa], cmdprog);
 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) != (data[0] & 0x00800080)) ||
 454               ((addr[1] & 0x00800080) != (data[1] & 0x00800080))) {
 455                if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 456                        write_via_fpu (chip, cmdres);
 457                        return (1);
 458                }
 459        }
 460
 461        write_via_fpu (chip, cmdres);
 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/*-----------------------------------------------------------------------
 475 */
 476static __inline__ unsigned long get_msr (void)
 477{
 478        unsigned long msr;
 479
 480        __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
 481
 482        return msr;
 483}
 484
 485static __inline__ void set_msr (unsigned long msr)
 486{
 487        __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
 488}
 489