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