uboot/board/netta2/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000-2004
   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/*-----------------------------------------------------------------------
  14 * Functions
  15 */
  16static ulong flash_get_size(vu_long * addr, flash_info_t * info);
  17static int write_byte(flash_info_t * info, ulong dest, uchar data);
  18static void flash_get_offsets(ulong base, flash_info_t * info);
  19
  20/*-----------------------------------------------------------------------
  21 */
  22
  23unsigned long flash_init(void)
  24{
  25        volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
  26        volatile memctl8xx_t *memctl = &immap->im_memctl;
  27        unsigned long size;
  28        int i;
  29
  30        /* Init: no FLASHes known */
  31        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i)
  32                flash_info[i].flash_id = FLASH_UNKNOWN;
  33
  34        size = flash_get_size((vu_long *) FLASH_BASE0_PRELIM, &flash_info[0]);
  35
  36        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
  37                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
  38                        size, size << 20);
  39        }
  40
  41        /* Remap FLASH according to real size */
  42        memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size & 0xFFFF8000);
  43        memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | (memctl->memc_br0 & ~(BR_BA_MSK));
  44
  45        /* Re-do sizing to get full correct info */
  46        size = flash_get_size((vu_long *) CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  47
  48        flash_get_offsets(CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  49
  50        /* monitor protection ON by default */
  51        flash_protect(FLAG_PROTECT_SET,
  52                        CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
  53                        &flash_info[0]);
  54
  55        flash_protect ( FLAG_PROTECT_SET,
  56                        CONFIG_ENV_ADDR,
  57                        CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
  58                        &flash_info[0]);
  59
  60#ifdef CONFIG_ENV_ADDR_REDUND
  61        flash_protect ( FLAG_PROTECT_SET,
  62                        CONFIG_ENV_ADDR_REDUND,
  63                        CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
  64                        &flash_info[0]);
  65#endif
  66
  67        flash_info[0].size = size;
  68
  69        return (size);
  70}
  71
  72/*-----------------------------------------------------------------------
  73 */
  74static void flash_get_offsets(ulong base, flash_info_t * info)
  75{
  76        int i;
  77
  78        /* set up sector start address table */
  79        if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) {
  80                for (i = 0; i < info->sector_count; i++) {
  81                        info->start[i] = base + (i * 0x00010000);
  82                }
  83        } else if (info->flash_id & FLASH_BTYPE) {
  84                /* set sector offsets for bottom boot block type    */
  85                info->start[0] = base + 0x00000000;
  86                info->start[1] = base + 0x00004000;
  87                info->start[2] = base + 0x00006000;
  88                info->start[3] = base + 0x00008000;
  89                for (i = 4; i < info->sector_count; i++) {
  90                        info->start[i] = base + (i * 0x00010000) - 0x00030000;
  91                }
  92        } else {
  93                /* set sector offsets for top boot block type       */
  94                i = info->sector_count - 1;
  95                info->start[i--] = base + info->size - 0x00004000;
  96                info->start[i--] = base + info->size - 0x00006000;
  97                info->start[i--] = base + info->size - 0x00008000;
  98                for (; i >= 0; i--) {
  99                        info->start[i] = base + i * 0x00010000;
 100                }
 101        }
 102}
 103
 104/*-----------------------------------------------------------------------
 105 */
 106void flash_print_info(flash_info_t * info)
 107{
 108        int i;
 109
 110        if (info->flash_id == FLASH_UNKNOWN) {
 111                printf("missing or unknown FLASH type\n");
 112                return;
 113        }
 114
 115        switch (info->flash_id & FLASH_VENDMASK) {
 116        case FLASH_MAN_AMD:
 117                printf("AMD ");
 118                break;
 119        case FLASH_MAN_FUJ:
 120                printf("FUJITSU ");
 121                break;
 122        case FLASH_MAN_MX:
 123                printf("MXIC ");
 124                break;
 125        default:
 126                printf("Unknown Vendor ");
 127                break;
 128        }
 129
 130        switch (info->flash_id & FLASH_TYPEMASK) {
 131        case FLASH_AM040:
 132                printf("AM29LV040B (4 Mbit, bottom boot sect)\n");
 133                break;
 134        case FLASH_AM400B:
 135                printf("AM29LV400B (4 Mbit, bottom boot sect)\n");
 136                break;
 137        case FLASH_AM400T:
 138                printf("AM29LV400T (4 Mbit, top boot sector)\n");
 139                break;
 140        case FLASH_AM800B:
 141                printf("AM29LV800B (8 Mbit, bottom boot sect)\n");
 142                break;
 143        case FLASH_AM800T:
 144                printf("AM29LV800T (8 Mbit, top boot sector)\n");
 145                break;
 146        case FLASH_AM160B:
 147                printf("AM29LV160B (16 Mbit, bottom boot sect)\n");
 148                break;
 149        case FLASH_AM160T:
 150                printf("AM29LV160T (16 Mbit, top boot sector)\n");
 151                break;
 152        case FLASH_AM320B:
 153                printf("AM29LV320B (32 Mbit, bottom boot sect)\n");
 154                break;
 155        case FLASH_AM320T:
 156                printf("AM29LV320T (32 Mbit, top boot sector)\n");
 157                break;
 158        default:
 159                printf("Unknown Chip Type\n");
 160                break;
 161        }
 162
 163        printf("  Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count);
 164
 165        printf("  Sector Start Addresses:");
 166        for (i = 0; i < info->sector_count; ++i) {
 167                if ((i % 5) == 0)
 168                        printf("\n   ");
 169                printf(" %08lX%s", info->start[i], info->protect[i] ? " (RO)" : "     ");
 170        }
 171        printf("\n");
 172}
 173
 174/*-----------------------------------------------------------------------
 175 */
 176
 177
 178/*-----------------------------------------------------------------------
 179 */
 180
 181/*
 182 * The following code cannot be run from FLASH!
 183 */
 184
 185static ulong flash_get_size(vu_long * addr, flash_info_t * info)
 186{
 187        short i;
 188        uchar mid;
 189        uchar pid;
 190        vu_char *caddr = (vu_char *) addr;
 191        ulong base = (ulong) addr;
 192
 193        /* Write auto select command: read Manufacturer ID */
 194        caddr[0x0555] = 0xAA;
 195        caddr[0x02AA] = 0x55;
 196        caddr[0x0555] = 0x90;
 197
 198        mid = caddr[0];
 199        switch (mid) {
 200        case (AMD_MANUFACT & 0xFF):
 201                info->flash_id = FLASH_MAN_AMD;
 202                break;
 203        case (FUJ_MANUFACT & 0xFF):
 204                info->flash_id = FLASH_MAN_FUJ;
 205                break;
 206        case (MX_MANUFACT & 0xFF):
 207                info->flash_id = FLASH_MAN_MX;
 208                break;
 209        case (STM_MANUFACT & 0xFF):
 210                info->flash_id = FLASH_MAN_STM;
 211                break;
 212        default:
 213                info->flash_id = FLASH_UNKNOWN;
 214                info->sector_count = 0;
 215                info->size = 0;
 216                return (0);                             /* no or unknown flash  */
 217        }
 218
 219        pid = caddr[1];                         /* device ID        */
 220        switch (pid) {
 221        case (AMD_ID_LV400T & 0xFF):
 222                info->flash_id += FLASH_AM400T;
 223                info->sector_count = 11;
 224                info->size = 0x00080000;
 225                break;                                  /* => 512 kB        */
 226
 227        case (AMD_ID_LV400B & 0xFF):
 228                info->flash_id += FLASH_AM400B;
 229                info->sector_count = 11;
 230                info->size = 0x00080000;
 231                break;                                  /* => 512 kB        */
 232
 233        case (AMD_ID_LV800T & 0xFF):
 234                info->flash_id += FLASH_AM800T;
 235                info->sector_count = 19;
 236                info->size = 0x00100000;
 237                break;                                  /* => 1 MB      */
 238
 239        case (AMD_ID_LV800B & 0xFF):
 240                info->flash_id += FLASH_AM800B;
 241                info->sector_count = 19;
 242                info->size = 0x00100000;
 243                break;                                  /* => 1 MB      */
 244
 245        case (AMD_ID_LV160T & 0xFF):
 246                info->flash_id += FLASH_AM160T;
 247                info->sector_count = 35;
 248                info->size = 0x00200000;
 249                break;                                  /* => 2 MB      */
 250
 251        case (AMD_ID_LV160B & 0xFF):
 252                info->flash_id += FLASH_AM160B;
 253                info->sector_count = 35;
 254                info->size = 0x00200000;
 255                break;                                  /* => 2 MB      */
 256
 257        case (AMD_ID_LV040B & 0xFF):
 258                info->flash_id += FLASH_AM040;
 259                info->sector_count = 8;
 260                info->size = 0x00080000;
 261                break;
 262
 263        case (STM_ID_M29W040B & 0xFF):
 264                info->flash_id += FLASH_AM040;
 265                info->sector_count = 8;
 266                info->size = 0x00080000;
 267                break;
 268
 269#if 0                                                   /* enable when device IDs are available */
 270        case (AMD_ID_LV320T & 0xFF):
 271                info->flash_id += FLASH_AM320T;
 272                info->sector_count = 67;
 273                info->size = 0x00400000;
 274                break;                                  /* => 4 MB      */
 275
 276        case (AMD_ID_LV320B & 0xFF):
 277                info->flash_id += FLASH_AM320B;
 278                info->sector_count = 67;
 279                info->size = 0x00400000;
 280                break;                                  /* => 4 MB      */
 281#endif
 282        default:
 283                info->flash_id = FLASH_UNKNOWN;
 284                return (0);                             /* => no or unknown flash */
 285
 286        }
 287
 288        printf(" ");
 289        /* set up sector start address table */
 290        if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) {
 291                for (i = 0; i < info->sector_count; i++) {
 292                        info->start[i] = base + (i * 0x00010000);
 293                }
 294        } else if (info->flash_id & FLASH_BTYPE) {
 295                /* set sector offsets for bottom boot block type    */
 296                info->start[0] = base + 0x00000000;
 297                info->start[1] = base + 0x00004000;
 298                info->start[2] = base + 0x00006000;
 299                info->start[3] = base + 0x00008000;
 300                for (i = 4; i < info->sector_count; i++) {
 301                        info->start[i] = base + (i * 0x00010000) - 0x00030000;
 302                }
 303        } else {
 304                /* set sector offsets for top boot block type       */
 305                i = info->sector_count - 1;
 306                info->start[i--] = base + info->size - 0x00004000;
 307                info->start[i--] = base + info->size - 0x00006000;
 308                info->start[i--] = base + info->size - 0x00008000;
 309                for (; i >= 0; i--) {
 310                        info->start[i] = base + i * 0x00010000;
 311                }
 312        }
 313
 314        /* check for protected sectors */
 315        for (i = 0; i < info->sector_count; i++) {
 316                /* read sector protection: D0 = 1 if protected */
 317                caddr = (volatile unsigned char *)(info->start[i]);
 318                info->protect[i] = caddr[2] & 1;
 319        }
 320
 321        /*
 322         * Prevent writes to uninitialized FLASH.
 323         */
 324        if (info->flash_id != FLASH_UNKNOWN) {
 325                caddr = (vu_char *) info->start[0];
 326
 327                caddr[0x0555] = 0xAA;
 328                caddr[0x02AA] = 0x55;
 329                caddr[0x0555] = 0xF0;
 330
 331                udelay(20000);
 332        }
 333
 334        return (info->size);
 335}
 336
 337
 338/*-----------------------------------------------------------------------
 339 */
 340
 341int flash_erase(flash_info_t * info, int s_first, int s_last)
 342{
 343        vu_char *addr = (vu_char *) (info->start[0]);
 344        int flag, prot, sect, l_sect;
 345        ulong start, now, last;
 346
 347        if ((s_first < 0) || (s_first > s_last)) {
 348                if (info->flash_id == FLASH_UNKNOWN) {
 349                        printf("- missing\n");
 350                } else {
 351                        printf("- no sectors to erase\n");
 352                }
 353                return 1;
 354        }
 355
 356        if ((info->flash_id == FLASH_UNKNOWN) ||
 357            (info->flash_id > FLASH_AMD_COMP)) {
 358                printf("Can't erase unknown flash type %08lx - aborted\n", info->flash_id);
 359                return 1;
 360        }
 361
 362        prot = 0;
 363        for (sect = s_first; sect <= s_last; ++sect) {
 364                if (info->protect[sect]) {
 365                        prot++;
 366                }
 367        }
 368
 369        if (prot) {
 370                printf("- Warning: %d protected sectors will not be erased!\n", prot);
 371        } else {
 372                printf("\n");
 373        }
 374
 375        l_sect = -1;
 376
 377        /* Disable interrupts which might cause a timeout here */
 378        flag = disable_interrupts();
 379
 380        addr[0x0555] = 0xAA;
 381        addr[0x02AA] = 0x55;
 382        addr[0x0555] = 0x80;
 383        addr[0x0555] = 0xAA;
 384        addr[0x02AA] = 0x55;
 385
 386        /* Start erase on unprotected sectors */
 387        for (sect = s_first; sect <= s_last; sect++) {
 388                if (info->protect[sect] == 0) { /* not protected */
 389                        addr = (vu_char *) (info->start[sect]);
 390                        addr[0] = 0x30;
 391                        l_sect = sect;
 392                }
 393        }
 394
 395        /* re-enable interrupts if necessary */
 396        if (flag)
 397                enable_interrupts();
 398
 399        /* wait at least 80us - let's wait 1 ms */
 400        udelay(1000);
 401
 402        /*
 403         * We wait for the last triggered sector
 404         */
 405        if (l_sect < 0)
 406                goto DONE;
 407
 408        start = get_timer(0);
 409        last = start;
 410        addr = (vu_char *) (info->start[l_sect]);
 411        while ((addr[0] & 0x80) != 0x80) {
 412                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 413                        printf("Timeout\n");
 414                        return 1;
 415                }
 416                /* show that we're waiting */
 417                if ((now - last) > 1000) {      /* every second */
 418                        putc('.');
 419                        last = now;
 420                }
 421        }
 422
 423DONE:
 424        /* reset to read mode */
 425        addr = (vu_char *) info->start[0];
 426        addr[0] = 0xF0;                         /* reset bank */
 427
 428        printf(" done\n");
 429        return 0;
 430}
 431
 432/*-----------------------------------------------------------------------
 433 * Copy memory to flash, returns:
 434 * 0 - OK
 435 * 1 - write timeout
 436 * 2 - Flash not erased
 437 */
 438
 439int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 440{
 441        int rc;
 442
 443        while (cnt > 0) {
 444                if ((rc = write_byte(info, addr++, *src++)) != 0) {
 445                        return (rc);
 446                }
 447                --cnt;
 448        }
 449
 450        return (0);
 451}
 452
 453/*-----------------------------------------------------------------------
 454 * Write a word to Flash, returns:
 455 * 0 - OK
 456 * 1 - write timeout
 457 * 2 - Flash not erased
 458 */
 459static int write_byte(flash_info_t * info, ulong dest, uchar data)
 460{
 461        vu_char *addr = (vu_char *) (info->start[0]);
 462        ulong start;
 463        int flag;
 464
 465        /* Check if Flash is (sufficiently) erased */
 466        if ((*((vu_char *) dest) & data) != data) {
 467                return (2);
 468        }
 469        /* Disable interrupts which might cause a timeout here */
 470        flag = disable_interrupts();
 471
 472        addr[0x0555] = 0xAA;
 473        addr[0x02AA] = 0x55;
 474        addr[0x0555] = 0xA0;
 475
 476        *((vu_char *) dest) = data;
 477
 478        /* re-enable interrupts if necessary */
 479        if (flag)
 480                enable_interrupts();
 481
 482        /* data polling for D7 */
 483        start = get_timer(0);
 484        while ((*((vu_char *) dest) & 0x80) != (data & 0x80)) {
 485                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 486                        return (1);
 487                }
 488        }
 489        return (0);
 490}
 491