uboot/board/ivm/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <mpc8xx.h>
  10
  11flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  12
  13#if defined(CONFIG_ENV_IS_IN_FLASH)
  14# ifndef  CONFIG_ENV_ADDR
  15#  define CONFIG_ENV_ADDR       (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
  16# endif
  17# ifndef  CONFIG_ENV_SIZE
  18#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
  19# endif
  20# ifndef  CONFIG_ENV_SECT_SIZE
  21#  define CONFIG_ENV_SECT_SIZE  CONFIG_ENV_SIZE
  22# endif
  23#endif
  24
  25/*-----------------------------------------------------------------------
  26 * Functions
  27 */
  28static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  29static int write_data (flash_info_t *info, ulong dest, ulong data);
  30static void flash_get_offsets (ulong base, flash_info_t *info);
  31
  32/*-----------------------------------------------------------------------
  33 */
  34
  35unsigned long flash_init (void)
  36{
  37        volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR;
  38        volatile memctl8xx_t *memctl = &immap->im_memctl;
  39        unsigned long size_b0;
  40        int i;
  41
  42        /* Init: no FLASHes known */
  43        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  44                flash_info[i].flash_id = FLASH_UNKNOWN;
  45        }
  46
  47        /* Static FLASH Bank configuration here - FIXME XXX */
  48
  49        size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
  50
  51        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
  52                printf ("## Unknown FLASH on Bank 0: "
  53                        "ID 0x%lx, Size = 0x%08lx = %ld MB\n",
  54                        flash_info[0].flash_id,
  55                        size_b0, size_b0<<20);
  56        }
  57
  58        /* Remap FLASH according to real size */
  59        memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
  60        memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | \
  61                                BR_MS_GPCM | BR_PS_16 | BR_V;
  62
  63        /* Re-do sizing to get full correct info */
  64        size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  65
  66        flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  67
  68        flash_info[0].size = size_b0;
  69
  70#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  71        /* monitor protection ON by default */
  72        flash_protect(FLAG_PROTECT_SET,
  73                      CONFIG_SYS_MONITOR_BASE,
  74                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  75                      &flash_info[0]);
  76#endif
  77
  78#ifdef  CONFIG_ENV_IS_IN_FLASH
  79        /* ENV protection ON by default */
  80        flash_protect(FLAG_PROTECT_SET,
  81                      CONFIG_ENV_ADDR,
  82                      CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
  83                      &flash_info[0]);
  84#endif
  85
  86        return (size_b0);
  87}
  88
  89/*-----------------------------------------------------------------------
  90 */
  91static void flash_get_offsets (ulong base, flash_info_t *info)
  92{
  93        int i;
  94
  95        if (info->flash_id == FLASH_UNKNOWN) {
  96                return;
  97        }
  98
  99        switch (info->flash_id & FLASH_VENDMASK) {
 100        case FLASH_MAN_MT:
 101            if (info->flash_id & FLASH_BTYPE) {
 102                /* set sector offsets for bottom boot block type        */
 103                info->start[0] = base + 0x00000000;
 104                info->start[1] = base + 0x00004000;
 105                info->start[2] = base + 0x00006000;
 106                info->start[3] = base + 0x00008000;
 107                for (i = 4; i < info->sector_count; i++) {
 108                        info->start[i] = base + ((i-3) * 0x00020000);
 109                }
 110            } else {
 111                /* set sector offsets for top boot block type           */
 112                i = info->sector_count - 1;
 113                info->start[i--] = base + info->size - 0x00004000;
 114                info->start[i--] = base + info->size - 0x00006000;
 115                info->start[i--] = base + info->size - 0x00008000;
 116                for (; i >= 0; i--) {
 117                        info->start[i] = base + i * 0x00020000;
 118                }
 119            }
 120            return;
 121
 122        case FLASH_MAN_SST:
 123            for (i = 0; i < info->sector_count; i++) {
 124                info->start[i] = base + (i * 0x00002000);
 125            }
 126            return;
 127
 128        case FLASH_MAN_AMD:
 129        case FLASH_MAN_FUJ:
 130
 131            /* set up sector start address table */
 132            if (info->flash_id & FLASH_BTYPE) {
 133                /* set sector offsets for bottom boot block type        */
 134                info->start[0] = base + 0x00000000;
 135                info->start[1] = base + 0x00008000;
 136                info->start[2] = base + 0x0000C000;
 137                info->start[3] = base + 0x00010000;
 138                for (i = 4; i < info->sector_count; i++) {
 139                        info->start[i] = base + (i * 0x00020000) - 0x00060000;
 140                }
 141            } else {
 142                /* set sector offsets for top boot block type           */
 143                i = info->sector_count - 1;
 144                info->start[i--] = base + info->size - 0x00008000;
 145                info->start[i--] = base + info->size - 0x0000C000;
 146                info->start[i--] = base + info->size - 0x00010000;
 147                for (; i >= 0; i--) {
 148                        info->start[i] = base + i * 0x00020000;
 149                }
 150            }
 151            return;
 152        default:
 153            printf ("Don't know sector ofsets for flash type 0x%lx\n",
 154                info->flash_id);
 155            return;
 156        }
 157}
 158
 159/*-----------------------------------------------------------------------
 160 */
 161void flash_print_info  (flash_info_t *info)
 162{
 163        int i;
 164
 165        if (info->flash_id == FLASH_UNKNOWN) {
 166                printf ("missing or unknown FLASH type\n");
 167                return;
 168        }
 169
 170        switch (info->flash_id & FLASH_VENDMASK) {
 171        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 172        case FLASH_MAN_FUJ:     printf ("Fujitsu ");            break;
 173        case FLASH_MAN_SST:     printf ("SST ");                break;
 174        case FLASH_MAN_STM:     printf ("STM ");                break;
 175        case FLASH_MAN_MT:      printf ("MT ");                 break;
 176        case FLASH_MAN_INTEL:   printf ("Intel ");              break;
 177        default:                printf ("Unknown Vendor ");     break;
 178        }
 179
 180        switch (info->flash_id & FLASH_TYPEMASK) {
 181        case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
 182                                break;
 183        case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
 184                                break;
 185        case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
 186                                break;
 187        case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
 188                                break;
 189        case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
 190                                break;
 191        case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
 192                                break;
 193        case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
 194                                break;
 195        case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
 196                                break;
 197        case FLASH_SST200A:     printf ("39xF200A (2M = 128K x 16)\n");
 198                                break;
 199        case FLASH_SST400A:     printf ("39xF400A (4M = 256K x 16)\n");
 200                                break;
 201        case FLASH_SST800A:     printf ("39xF800A (8M = 512K x 16)\n");
 202                                break;
 203        case FLASH_STM800AB:    printf ("M29W800AB (8M = 512K x 16)\n");
 204                                break;
 205        case FLASH_28F008S5:    printf ("28F008S5 (1M = 64K x 16)\n");
 206                                break;
 207        case FLASH_28F400_T:    printf ("28F400B3 (4Mbit, top boot sector)\n");
 208                                break;
 209        case FLASH_28F400_B:    printf ("28F400B3 (4Mbit, bottom boot sector)\n");
 210                                break;
 211        default:                printf ("Unknown Chip Type\n");
 212                                break;
 213        }
 214
 215        if (info->size >= (1 << 20)) {
 216                i = 20;
 217        } else {
 218                i = 10;
 219        }
 220        printf ("  Size: %ld %cB in %d Sectors\n",
 221                info->size >> i,
 222                (i == 20) ? 'M' : 'k',
 223                info->sector_count);
 224
 225        printf ("  Sector Start Addresses:");
 226        for (i=0; i<info->sector_count; ++i) {
 227                if ((i % 5) == 0)
 228                        printf ("\n   ");
 229                printf (" %08lX%s",
 230                        info->start[i],
 231                        info->protect[i] ? " (RO)" : "     "
 232                );
 233        }
 234        printf ("\n");
 235        return;
 236}
 237
 238/*-----------------------------------------------------------------------
 239 */
 240
 241
 242/*-----------------------------------------------------------------------
 243 */
 244
 245/*
 246 * The following code cannot be run from FLASH!
 247 */
 248
 249static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 250{
 251        ushort value;
 252        vu_short *saddr = (vu_short *)addr;
 253
 254        /* Read Manufacturer ID */
 255        saddr[0] = 0x0090;
 256        value = saddr[0];
 257
 258        switch (value) {
 259        case (AMD_MANUFACT & 0xFFFF):
 260                info->flash_id = FLASH_MAN_AMD;
 261                break;
 262        case (FUJ_MANUFACT & 0xFFFF):
 263                info->flash_id = FLASH_MAN_FUJ;
 264                break;
 265        case (SST_MANUFACT & 0xFFFF):
 266                info->flash_id = FLASH_MAN_SST;
 267                break;
 268        case (STM_MANUFACT & 0xFFFF):
 269                info->flash_id = FLASH_MAN_STM;
 270                break;
 271        case (MT_MANUFACT & 0xFFFF):
 272                info->flash_id = FLASH_MAN_MT;
 273                break;
 274        default:
 275                info->flash_id = FLASH_UNKNOWN;
 276                info->sector_count = 0;
 277                info->size = 0;
 278                saddr[0] = 0x00FF;              /* restore read mode */
 279                return (0);                     /* no or unknown flash  */
 280        }
 281
 282        value = saddr[1];                       /* device ID            */
 283
 284        switch (value) {
 285        case (AMD_ID_LV400T & 0xFFFF):
 286                info->flash_id += FLASH_AM400T;
 287                info->sector_count = 11;
 288                info->size = 0x00100000;
 289                break;                          /* => 1 MB              */
 290
 291        case (AMD_ID_LV400B & 0xFFFF):
 292                info->flash_id += FLASH_AM400B;
 293                info->sector_count = 11;
 294                info->size = 0x00100000;
 295                break;                          /* => 1 MB              */
 296
 297        case (AMD_ID_LV800T & 0xFFFF):
 298                info->flash_id += FLASH_AM800T;
 299                info->sector_count = 19;
 300                info->size = 0x00200000;
 301                break;                          /* => 2 MB              */
 302
 303        case (AMD_ID_LV800B & 0xFFFF):
 304                info->flash_id += FLASH_AM800B;
 305                info->sector_count = 19;
 306                info->size = 0x00200000;
 307                break;                          /* => 2 MB              */
 308
 309        case (AMD_ID_LV160T & 0xFFFF):
 310                info->flash_id += FLASH_AM160T;
 311                info->sector_count = 35;
 312                info->size = 0x00400000;
 313                break;                          /* => 4 MB              */
 314
 315        case (AMD_ID_LV160B & 0xFFFF):
 316                info->flash_id += FLASH_AM160B;
 317                info->sector_count = 35;
 318                info->size = 0x00400000;
 319                break;                          /* => 4 MB              */
 320#if 0   /* enable when device IDs are available */
 321        case (AMD_ID_LV320T & 0xFFFF):
 322                info->flash_id += FLASH_AM320T;
 323                info->sector_count = 67;
 324                info->size = 0x00800000;
 325                break;                          /* => 8 MB              */
 326
 327        case (AMD_ID_LV320B & 0xFFFF):
 328                info->flash_id += FLASH_AM320B;
 329                info->sector_count = 67;
 330                info->size = 0x00800000;
 331                break;                          /* => 8 MB              */
 332#endif
 333        case (SST_ID_xF200A & 0xFFFF):
 334                info->flash_id += FLASH_SST200A;
 335                info->sector_count = 64;        /* 39xF200A ID ( 2M = 128K x 16 ) */
 336                info->size = 0x00080000;
 337                break;
 338        case (SST_ID_xF400A & 0xFFFF):
 339                info->flash_id += FLASH_SST400A;
 340                info->sector_count = 128;       /* 39xF400A ID ( 4M = 256K x 16 ) */
 341                info->size = 0x00100000;
 342                break;
 343        case (SST_ID_xF800A & 0xFFFF):
 344                info->flash_id += FLASH_SST800A;
 345                info->sector_count = 256;       /* 39xF800A ID ( 8M = 512K x 16 ) */
 346                info->size = 0x00200000;
 347                break;                          /* => 2 MB              */
 348        case (STM_ID_x800AB & 0xFFFF):
 349                info->flash_id += FLASH_STM800AB;
 350                info->sector_count = 19;
 351                info->size = 0x00200000;
 352                break;                          /* => 2 MB              */
 353        case (MT_ID_28F400_T & 0xFFFF):
 354                info->flash_id += FLASH_28F400_T;
 355                info->sector_count = 7;
 356                info->size = 0x00080000;
 357                break;                          /* => 512 kB            */
 358        case (MT_ID_28F400_B & 0xFFFF):
 359                info->flash_id += FLASH_28F400_B;
 360                info->sector_count = 7;
 361                info->size = 0x00080000;
 362                break;                          /* => 512 kB            */
 363        default:
 364                info->flash_id = FLASH_UNKNOWN;
 365                saddr[0] = 0x00FF;              /* restore read mode */
 366                return (0);                     /* => no or unknown flash */
 367
 368        }
 369
 370        if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
 371                printf ("** ERROR: sector count %d > max (%d) **\n",
 372                        info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
 373                info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 374        }
 375
 376        saddr[0] = 0x00FF;              /* restore read mode */
 377
 378        return (info->size);
 379}
 380
 381
 382/*-----------------------------------------------------------------------
 383 */
 384
 385int     flash_erase (flash_info_t *info, int s_first, int s_last)
 386{
 387        int flag, prot, sect;
 388        ulong start, now, last;
 389
 390        if ((s_first < 0) || (s_first > s_last)) {
 391                if (info->flash_id == FLASH_UNKNOWN) {
 392                        printf ("- missing\n");
 393                } else {
 394                        printf ("- no sectors to erase\n");
 395                }
 396                return 1;
 397        }
 398
 399        if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_MT) {
 400                printf ("Can erase only MT flash types - aborted\n");
 401                return 1;
 402        }
 403
 404        prot = 0;
 405        for (sect=s_first; sect<=s_last; ++sect) {
 406                if (info->protect[sect]) {
 407                        prot++;
 408                }
 409        }
 410
 411        if (prot) {
 412                printf ("- Warning: %d protected sectors will not be erased!\n",
 413                        prot);
 414        } else {
 415                printf ("\n");
 416        }
 417
 418        start = get_timer (0);
 419        last  = start;
 420        /* Start erase on unprotected sectors */
 421        for (sect = s_first; sect<=s_last; sect++) {
 422                if (info->protect[sect] == 0) { /* not protected */
 423                        vu_short *addr = (vu_short *)(info->start[sect]);
 424                        unsigned short status;
 425
 426                        /* Disable interrupts which might cause a timeout here */
 427                        flag = disable_interrupts();
 428
 429                        *addr = 0x0050; /* clear status register */
 430                        *addr = 0x0020; /* erase setup */
 431                        *addr = 0x00D0; /* erase confirm */
 432
 433                        /* re-enable interrupts if necessary */
 434                        if (flag)
 435                                enable_interrupts();
 436
 437                        /* wait at least 80us - let's wait 1 ms */
 438                        udelay (1000);
 439
 440                        while (((status = *addr) & 0x0080) != 0x0080) {
 441                                if ((now=get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 442                                        printf ("Timeout\n");
 443                                        *addr = 0x00FF; /* reset to read mode */
 444                                        return 1;
 445                                }
 446
 447                                /* show that we're waiting */
 448                                if ((now - last) > 1000) {      /* every second */
 449                                        putc ('.');
 450                                        last = now;
 451                                }
 452                        }
 453
 454                        *addr = 0x00FF; /* reset to read mode */
 455                }
 456        }
 457        printf (" done\n");
 458        return 0;
 459}
 460
 461/*-----------------------------------------------------------------------
 462 * Copy memory to flash, returns:
 463 * 0 - OK
 464 * 1 - write timeout
 465 * 2 - Flash not erased
 466 * 4 - Flash not identified
 467 */
 468
 469#define FLASH_WIDTH     2       /* flash bus width in bytes */
 470
 471int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 472{
 473        ulong cp, wp, data;
 474        int i, l, rc;
 475
 476        if (info->flash_id == FLASH_UNKNOWN) {
 477                return 4;
 478        }
 479
 480        wp = (addr & ~(FLASH_WIDTH-1)); /* get lower FLASH_WIDTH aligned address */
 481
 482        /*
 483         * handle unaligned start bytes
 484         */
 485        if ((l = addr - wp) != 0) {
 486                data = 0;
 487                for (i=0, cp=wp; i<l; ++i, ++cp) {
 488                        data = (data << 8) | (*(uchar *)cp);
 489                }
 490                for (; i<FLASH_WIDTH && cnt>0; ++i) {
 491                        data = (data << 8) | *src++;
 492                        --cnt;
 493                        ++cp;
 494                }
 495                for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) {
 496                        data = (data << 8) | (*(uchar *)cp);
 497                }
 498
 499                if ((rc = write_data(info, wp, data)) != 0) {
 500                        return (rc);
 501                }
 502                wp += FLASH_WIDTH;
 503        }
 504
 505        /*
 506         * handle FLASH_WIDTH aligned part
 507         */
 508        while (cnt >= FLASH_WIDTH) {
 509                data = 0;
 510                for (i=0; i<FLASH_WIDTH; ++i) {
 511                        data = (data << 8) | *src++;
 512                }
 513                if ((rc = write_data(info, wp, data)) != 0) {
 514                        return (rc);
 515                }
 516                wp  += FLASH_WIDTH;
 517                cnt -= FLASH_WIDTH;
 518        }
 519
 520        if (cnt == 0) {
 521                return (0);
 522        }
 523
 524        /*
 525         * handle unaligned tail bytes
 526         */
 527        data = 0;
 528        for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) {
 529                data = (data << 8) | *src++;
 530                --cnt;
 531        }
 532        for (; i<FLASH_WIDTH; ++i, ++cp) {
 533                data = (data << 8) | (*(uchar *)cp);
 534        }
 535
 536        return (write_data(info, wp, data));
 537}
 538
 539/*-----------------------------------------------------------------------
 540 * Write a word to Flash, returns:
 541 * 0 - OK
 542 * 1 - write timeout
 543 * 2 - Flash not erased
 544 */
 545static int write_data (flash_info_t *info, ulong dest, ulong data)
 546{
 547        vu_short *addr = (vu_short *)dest;
 548        ushort sdata = (ushort)data;
 549        ushort status;
 550        ulong start;
 551        int flag;
 552
 553        /* Check if Flash is (sufficiently) erased */
 554        if ((*addr & sdata) != sdata) {
 555                return (2);
 556        }
 557        /* Disable interrupts which might cause a timeout here */
 558        flag = disable_interrupts();
 559
 560        *addr = 0x0040;         /* write setup */
 561        *addr = sdata;
 562
 563        /* re-enable interrupts if necessary */
 564        if (flag)
 565                enable_interrupts();
 566
 567        start = get_timer (0);
 568
 569        while (((status = *addr) & 0x0080) != 0x0080) {
 570                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 571                        *addr = 0x00FF; /* restore read mode */
 572                        return (1);
 573                }
 574        }
 575
 576        *addr = 0x00FF;         /* restore read mode */
 577
 578        return (0);
 579}
 580
 581/*-----------------------------------------------------------------------
 582 */
 583