uboot/board/icecube/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9
  10#ifndef CONFIG_FLASH_CFI_DRIVER
  11flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  12
  13/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it
  14 *        has nothing to do with the flash chip being 8-bit or 16-bit.
  15 */
  16#ifdef CONFIG_FLASH_16BIT
  17typedef unsigned short FLASH_PORT_WIDTH;
  18typedef volatile unsigned short FLASH_PORT_WIDTHV;
  19#define FLASH_ID_MASK   0xFFFF
  20#else
  21typedef unsigned char FLASH_PORT_WIDTH;
  22typedef volatile unsigned char FLASH_PORT_WIDTHV;
  23#define FLASH_ID_MASK   0xFF
  24#endif
  25
  26#define FPW     FLASH_PORT_WIDTH
  27#define FPWV    FLASH_PORT_WIDTHV
  28
  29#define ORMASK(size) ((-size) & OR_AM_MSK)
  30
  31#define FLASH_CYCLE1    0x0555
  32#define FLASH_CYCLE2    0x02aa
  33
  34/*-----------------------------------------------------------------------
  35 * Functions
  36 */
  37static ulong flash_get_size(FPWV *addr, flash_info_t *info);
  38static void flash_reset(flash_info_t *info);
  39static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data);
  40static flash_info_t *flash_get_info(ulong base);
  41
  42/*-----------------------------------------------------------------------
  43 * flash_init()
  44 *
  45 * sets up flash_info and returns size of FLASH (bytes)
  46 */
  47unsigned long flash_init (void)
  48{
  49        unsigned long size = 0;
  50        int i;
  51        extern void flash_preinit(void);
  52        extern void flash_afterinit(ulong);
  53        ulong flashbase = CONFIG_SYS_FLASH_BASE;
  54
  55        flash_preinit();
  56
  57        /* Init: no FLASHes known */
  58        for (i=0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  59                memset(&flash_info[i], 0, sizeof(flash_info_t));
  60
  61                flash_info[i].size =
  62                        flash_get_size((FPW *)flashbase, &flash_info[i]);
  63
  64                size += flash_info[i].size;
  65                flashbase += 0x800000;
  66        }
  67#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  68        /* monitor protection ON by default */
  69        flash_protect(FLAG_PROTECT_SET,
  70                      CONFIG_SYS_MONITOR_BASE,
  71                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  72                      flash_get_info(CONFIG_SYS_MONITOR_BASE));
  73#endif
  74
  75#ifdef  CONFIG_ENV_IS_IN_FLASH
  76        /* ENV protection ON by default */
  77        flash_protect(FLAG_PROTECT_SET,
  78                      CONFIG_ENV_ADDR,
  79                      CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
  80                      flash_get_info(CONFIG_ENV_ADDR));
  81#endif
  82
  83
  84        flash_afterinit(size);
  85        return size ? size : 1;
  86}
  87
  88/*-----------------------------------------------------------------------
  89 */
  90static void flash_reset(flash_info_t *info)
  91{
  92        FPWV *base = (FPWV *)(info->start[0]);
  93
  94        /* Put FLASH back in read mode */
  95        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
  96                *base = (FPW)0x00FF00FF;        /* Intel Read Mode */
  97        else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
  98                *base = (FPW)0x00F000F0;        /* AMD Read Mode */
  99}
 100
 101/*-----------------------------------------------------------------------
 102 */
 103
 104static flash_info_t *flash_get_info(ulong base)
 105{
 106        int i;
 107        flash_info_t * info;
 108
 109        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
 110                info = & flash_info[i];
 111                if (info->size &&
 112                        info->start[0] <= base && base <= info->start[0] + info->size - 1)
 113                        break;
 114        }
 115
 116        return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
 117}
 118
 119/*-----------------------------------------------------------------------
 120 */
 121
 122void flash_print_info (flash_info_t *info)
 123{
 124        int i;
 125        uchar *boottype;
 126        uchar *bootletter;
 127        char *fmt;
 128        uchar botbootletter[] = "B";
 129        uchar topbootletter[] = "T";
 130        uchar botboottype[] = "bottom boot sector";
 131        uchar topboottype[] = "top boot sector";
 132
 133        if (info->flash_id == FLASH_UNKNOWN) {
 134                printf ("missing or unknown FLASH type\n");
 135                return;
 136        }
 137
 138        switch (info->flash_id & FLASH_VENDMASK) {
 139        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 140        case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
 141        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
 142        case FLASH_MAN_SST:     printf ("SST ");                break;
 143        case FLASH_MAN_STM:     printf ("STM ");                break;
 144        case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
 145        default:                printf ("Unknown Vendor ");     break;
 146        }
 147
 148        /* check for top or bottom boot, if it applies */
 149        if (info->flash_id & FLASH_BTYPE) {
 150                boottype = botboottype;
 151                bootletter = botbootletter;
 152        }
 153        else {
 154                boottype = topboottype;
 155                bootletter = topbootletter;
 156        }
 157
 158        switch (info->flash_id & FLASH_TYPEMASK) {
 159        case FLASH_AMDLV065D:
 160                fmt = "29LV065 (64 Mbit, uniform sectors)\n";
 161                break;
 162        default:
 163                fmt = "Unknown Chip Type\n";
 164                break;
 165        }
 166
 167        printf (fmt, bootletter, boottype);
 168
 169        printf ("  Size: %ld MB in %d Sectors\n",
 170                info->size >> 20,
 171                info->sector_count);
 172
 173        printf ("  Sector Start Addresses:");
 174
 175        for (i=0; i<info->sector_count; ++i) {
 176                if ((i % 5) == 0) {
 177                        printf ("\n   ");
 178                }
 179
 180                printf (" %08lX%s", info->start[i],
 181                        info->protect[i] ? " (RO)" : "     ");
 182        }
 183
 184        printf ("\n");
 185}
 186
 187/*-----------------------------------------------------------------------
 188 */
 189
 190/*
 191 * The following code cannot be run from FLASH!
 192 */
 193
 194ulong flash_get_size (FPWV *addr, flash_info_t *info)
 195{
 196        int i;
 197        FPWV* addr2;
 198
 199        /* Write auto select command: read Manufacturer ID */
 200        /* Write auto select command sequence and test FLASH answer */
 201        addr[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* for AMD, Intel ignores this */
 202        addr[FLASH_CYCLE2] = (FPW)0x00550055;   /* for AMD, Intel ignores this */
 203        addr[FLASH_CYCLE1] = (FPW)0x00900090;   /* selects Intel or AMD */
 204
 205        /* The manufacturer codes are only 1 byte, so just use 1 byte.
 206         * This works for any bus width and any FLASH device width.
 207         */
 208        udelay(100);
 209        switch (addr[0] & 0xff) {
 210
 211        case (uchar)AMD_MANUFACT:
 212                info->flash_id = FLASH_MAN_AMD;
 213                break;
 214
 215        case (uchar)INTEL_MANUFACT:
 216                info->flash_id = FLASH_MAN_INTEL;
 217                break;
 218
 219        default:
 220                info->flash_id = FLASH_UNKNOWN;
 221                info->sector_count = 0;
 222                info->size = 0;
 223                break;
 224        }
 225
 226        /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */
 227        if (info->flash_id != FLASH_UNKNOWN) switch ((FPW)addr[1]) {
 228
 229        case (FPW)AMD_ID_LV065D:
 230                info->flash_id += FLASH_AMDLV065D;
 231                info->sector_count = 128;
 232                info->size = 0x00800000;
 233                for( i = 0; i < info->sector_count; i++ )
 234                        info->start[i] = (ulong)addr + (i * 0x10000);
 235                break;                          /* => 8 or 16 MB        */
 236
 237        default:
 238                info->flash_id = FLASH_UNKNOWN;
 239                info->sector_count = 0;
 240                info->size = 0;
 241                return (0);                     /* => no or unknown flash */
 242        }
 243
 244        /* test for real flash at bank 1 */
 245        addr2 = (FPW *)((ulong)addr | 0x800000);
 246        if (addr2 != addr &&
 247                ((addr2[0] & 0xff) == (addr[0] & 0xff)) && ((FPW)addr2[1] == (FPW)addr[1])) {
 248                /* Seems 2 banks are the same space (8Mb chip is installed,
 249                 * J24 in default position (CS0)). Disable this (first) bank.
 250                 */
 251                info->flash_id = FLASH_UNKNOWN;
 252                info->sector_count = 0;
 253                info->size = 0;
 254        }
 255        /* Put FLASH back in read mode */
 256        flash_reset(info);
 257
 258        return (info->size);
 259}
 260
 261/*-----------------------------------------------------------------------
 262 */
 263
 264int     flash_erase (flash_info_t *info, int s_first, int s_last)
 265{
 266        FPWV *addr;
 267        int flag, prot, sect;
 268        int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL;
 269        ulong start, now, last;
 270        int rcode = 0;
 271
 272        if ((s_first < 0) || (s_first > s_last)) {
 273                if (info->flash_id == FLASH_UNKNOWN) {
 274                        printf ("- missing\n");
 275                } else {
 276                        printf ("- no sectors to erase\n");
 277                }
 278                return 1;
 279        }
 280
 281        switch (info->flash_id & FLASH_TYPEMASK) {
 282        case FLASH_AMDLV065D:
 283                break;
 284        case FLASH_UNKNOWN:
 285        default:
 286                printf ("Can't erase unknown flash type %08lx - aborted\n",
 287                        info->flash_id);
 288                return 1;
 289        }
 290
 291        prot = 0;
 292        for (sect=s_first; sect<=s_last; ++sect) {
 293                if (info->protect[sect]) {
 294                        prot++;
 295                }
 296        }
 297
 298        if (prot) {
 299                printf ("- Warning: %d protected sectors will not be erased!\n",
 300                        prot);
 301        } else {
 302                printf ("\n");
 303        }
 304
 305        last  = get_timer(0);
 306
 307        /* Start erase on unprotected sectors */
 308        for (sect = s_first; sect<=s_last && rcode == 0; sect++) {
 309
 310                if (info->protect[sect] != 0)   /* protected, skip it */
 311                        continue;
 312
 313                /* Disable interrupts which might cause a timeout here */
 314                flag = disable_interrupts();
 315
 316                addr = (FPWV *)(info->start[sect]);
 317                if (intel) {
 318                        *addr = (FPW)0x00500050; /* clear status register */
 319                        *addr = (FPW)0x00200020; /* erase setup */
 320                        *addr = (FPW)0x00D000D0; /* erase confirm */
 321                }
 322                else {
 323                        /* must be AMD style if not Intel */
 324                        FPWV *base;             /* first address in bank */
 325
 326                        base = (FPWV *)(info->start[0]);
 327                        base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
 328                        base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
 329                        base[FLASH_CYCLE1] = (FPW)0x00800080;   /* erase mode */
 330                        base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
 331                        base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
 332                        *addr = (FPW)0x00300030;        /* erase sector */
 333                }
 334
 335                /* re-enable interrupts if necessary */
 336                if (flag)
 337                        enable_interrupts();
 338
 339                start = get_timer(0);
 340
 341                /* wait at least 50us for AMD, 80us for Intel.
 342                 * Let's wait 1 ms.
 343                 */
 344                udelay (1000);
 345
 346                while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) {
 347                        if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 348                                printf ("Timeout\n");
 349
 350                                if (intel) {
 351                                        /* suspend erase        */
 352                                        *addr = (FPW)0x00B000B0;
 353                                }
 354
 355                                flash_reset(info);      /* reset to read mode */
 356                                rcode = 1;              /* failed */
 357                                break;
 358                        }
 359
 360                        /* show that we're waiting */
 361                        if ((get_timer(last)) > CONFIG_SYS_HZ) {/* every second */
 362                                putc ('.');
 363                                last = get_timer(0);
 364                        }
 365                }
 366
 367                /* show that we're waiting */
 368                if ((get_timer(last)) > CONFIG_SYS_HZ) {        /* every second */
 369                        putc ('.');
 370                        last = get_timer(0);
 371                }
 372
 373                flash_reset(info);      /* reset to read mode   */
 374        }
 375
 376        printf (" done\n");
 377        return rcode;
 378}
 379
 380/*-----------------------------------------------------------------------
 381 * Copy memory to flash, returns:
 382 * 0 - OK
 383 * 1 - write timeout
 384 * 2 - Flash not erased
 385 */
 386int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 387{
 388        FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */
 389        int bytes;        /* number of bytes to program in current word         */
 390        int left;         /* number of bytes left to program                    */
 391        int i, res;
 392
 393        for (left = cnt, res = 0;
 394                 left > 0 && res == 0;
 395                 addr += sizeof(data), left -= sizeof(data) - bytes) {
 396
 397                bytes = addr & (sizeof(data) - 1);
 398                addr &= ~(sizeof(data) - 1);
 399
 400                /* combine source and destination data so can program
 401                 * an entire word of 16 or 32 bits
 402                 */
 403                for (i = 0; i < sizeof(data); i++) {
 404                        data <<= 8;
 405                        if (i < bytes || i - bytes >= left )
 406                                data += *((uchar *)addr + i);
 407                        else
 408                                data += *src++;
 409                }
 410
 411                /* write one word to the flash */
 412                switch (info->flash_id & FLASH_VENDMASK) {
 413                case FLASH_MAN_AMD:
 414                        res = write_word_amd(info, (FPWV *)addr, data);
 415                        break;
 416                default:
 417                        /* unknown flash type, error! */
 418                        printf ("missing or unknown FLASH type\n");
 419                        res = 1;        /* not really a timeout, but gives error */
 420                        break;
 421                }
 422        }
 423
 424        return (res);
 425}
 426
 427/*-----------------------------------------------------------------------
 428 * Write a word to Flash for AMD FLASH
 429 * A word is 16 or 32 bits, whichever the bus width of the flash bank
 430 * (not an individual chip) is.
 431 *
 432 * returns:
 433 * 0 - OK
 434 * 1 - write timeout
 435 * 2 - Flash not erased
 436 */
 437static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data)
 438{
 439        ulong start;
 440        int flag;
 441        int res = 0;    /* result, assume success       */
 442        FPWV *base;             /* first address in flash bank  */
 443
 444        /* Check if Flash is (sufficiently) erased */
 445        if ((*dest & data) != data) {
 446                return (2);
 447        }
 448
 449
 450        base = (FPWV *)(info->start[0]);
 451
 452        /* Disable interrupts which might cause a timeout here */
 453        flag = disable_interrupts();
 454
 455        base[FLASH_CYCLE1] = (FPW)0x00AA00AA;   /* unlock */
 456        base[FLASH_CYCLE2] = (FPW)0x00550055;   /* unlock */
 457        base[FLASH_CYCLE1] = (FPW)0x00A000A0;   /* selects program mode */
 458
 459        *dest = data;           /* start programming the data   */
 460
 461        /* re-enable interrupts if necessary */
 462        if (flag)
 463                enable_interrupts();
 464
 465        start = get_timer (0);
 466
 467        /* data polling for D7 */
 468        while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) {
 469                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 470                        *dest = (FPW)0x00F000F0;        /* reset bank */
 471                        res = 1;
 472                }
 473        }
 474
 475        return (res);
 476}
 477#endif /*CONFIG_FLASH_CFI_DRIVER*/
 478