uboot/board/cmc_pu2/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003-2004
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * (C) Copyright 2004
   6 * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
   7 *
   8 * Modified for the CMC PU2 by (C) Copyright 2004 Gary Jennejohn
   9 * garyj@denx.de
  10 *
  11 * See file CREDITS for list of people who contributed to this
  12 * project.
  13 *
  14 * This program is free software; you can redistribute it and/or
  15 * modify it under the terms of the GNU General Public License as
  16 * published by the Free Software Foundation; either version 2 of
  17 * the License, or (at your option) any later version.
  18 *
  19 * This program is distributed in the hope that it will be useful,
  20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22 * GNU General Public License for more details.
  23 *
  24 * You should have received a copy of the GNU General Public License
  25 * along with this program; if not, write to the Free Software
  26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  27 * MA 02111-1307 USA
  28 */
  29
  30#include <common.h>
  31
  32#ifndef CONFIG_ENV_ADDR
  33#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
  34#endif
  35
  36flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  37
  38#define FLASH_CYCLE1    0x0555
  39#define FLASH_CYCLE2    0x02AA
  40
  41/*-----------------------------------------------------------------------
  42 * Functions
  43 */
  44static ulong flash_get_size(vu_short *addr, flash_info_t *info);
  45static void flash_reset(flash_info_t *info);
  46static int write_word_amd(flash_info_t *info, vu_short *dest, ushort data);
  47static flash_info_t *flash_get_info(ulong base);
  48
  49/*-----------------------------------------------------------------------
  50 * flash_init()
  51 *
  52 * sets up flash_info and returns size of FLASH (bytes)
  53 */
  54unsigned long flash_init (void)
  55{
  56        unsigned long size = 0;
  57        ulong flashbase = CONFIG_SYS_FLASH_BASE;
  58
  59        /* Init: no FLASHes known */
  60        memset(&flash_info[0], 0, sizeof(flash_info_t));
  61
  62        flash_info[0].size = flash_get_size((vu_short *)flashbase, &flash_info[0]);
  63
  64        size = flash_info[0].size;
  65
  66#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  67        /* monitor protection ON by default */
  68        flash_protect(FLAG_PROTECT_SET,
  69                      CONFIG_SYS_MONITOR_BASE,
  70                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  71                      flash_get_info(CONFIG_SYS_MONITOR_BASE));
  72#endif
  73
  74#ifdef  CONFIG_ENV_IS_IN_FLASH
  75        /* ENV protection ON by default */
  76        flash_protect(FLAG_PROTECT_SET,
  77                      CONFIG_ENV_ADDR,
  78                      CONFIG_ENV_ADDR+CONFIG_ENV_SIZE-1,
  79                      flash_get_info(CONFIG_ENV_ADDR));
  80#endif
  81
  82        return size ? size : 1;
  83}
  84
  85/*-----------------------------------------------------------------------
  86 */
  87static void flash_reset(flash_info_t *info)
  88{
  89        vu_short *base = (vu_short *)(info->start[0]);
  90
  91        /* Put FLASH back in read mode */
  92        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
  93                *base = 0x00FF; /* Intel Read Mode */
  94        else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD)
  95                *base = 0x00F0; /* AMD Read Mode */
  96}
  97
  98/*-----------------------------------------------------------------------
  99 */
 100
 101static flash_info_t *flash_get_info(ulong base)
 102{
 103        int i;
 104        flash_info_t * info;
 105
 106        info = NULL;
 107        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i ++) {
 108                info = & flash_info[i];
 109                if (info->size && info->start[0] <= base &&
 110                    base <= info->start[0] + info->size - 1)
 111                        break;
 112        }
 113
 114        return i == CONFIG_SYS_MAX_FLASH_BANKS ? 0 : info;
 115}
 116
 117/*-----------------------------------------------------------------------
 118 */
 119
 120void flash_print_info (flash_info_t *info)
 121{
 122        int i;
 123
 124        if (info->flash_id == FLASH_UNKNOWN) {
 125                printf ("missing or unknown FLASH type\n");
 126                return;
 127        }
 128
 129        switch (info->flash_id & FLASH_VENDMASK) {
 130        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 131        case FLASH_MAN_BM:      printf ("BRIGHT MICRO ");       break;
 132        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
 133        case FLASH_MAN_SST:     printf ("SST ");                break;
 134        case FLASH_MAN_STM:     printf ("STM ");                break;
 135        case FLASH_MAN_INTEL:   printf ("INTEL ");              break;
 136        default:                printf ("Unknown Vendor ");     break;
 137        }
 138
 139        switch (info->flash_id & FLASH_TYPEMASK) {
 140        case FLASH_S29GL064M:
 141                printf ("S29GL064M-R6 (64Mbit, uniform sector size)\n");
 142                break;
 143        default:
 144                printf ("Unknown Chip Type\n");
 145                break;
 146        }
 147
 148        printf ("  Size: %ld MB in %d Sectors\n",
 149                info->size >> 20,
 150                info->sector_count);
 151
 152        printf ("  Sector Start Addresses:");
 153
 154        for (i=0; i<info->sector_count; ++i) {
 155                if ((i % 5) == 0) {
 156                        printf ("\n   ");
 157                }
 158                printf (" %08lX%s",
 159                        info->start[i],
 160                        info->protect[i] ? " (RO)" : "     ");
 161        }
 162        printf ("\n");
 163        return;
 164}
 165
 166/*-----------------------------------------------------------------------
 167 */
 168
 169/*
 170 * The following code cannot be run from FLASH!
 171 */
 172
 173ulong flash_get_size (vu_short *addr, flash_info_t *info)
 174{
 175        int i;
 176        ushort value;
 177        ulong base = (ulong)addr;
 178
 179        /* Write auto select command sequence */
 180        addr[FLASH_CYCLE1] = 0x00AA;    /* for AMD, Intel ignores this */
 181        addr[FLASH_CYCLE2] = 0x0055;    /* for AMD, Intel ignores this */
 182        addr[FLASH_CYCLE1] = 0x0090;    /* selects Intel or AMD */
 183
 184        /* read Manufacturer ID */
 185        udelay(100);
 186        value = addr[0];
 187        debug ("Manufacturer ID: %04X\n", value);
 188
 189        switch (value) {
 190
 191        case (AMD_MANUFACT & 0xFFFF):
 192                debug ("Manufacturer: AMD (Spansion)\n");
 193                info->flash_id = FLASH_MAN_AMD;
 194                break;
 195
 196        case (INTEL_MANUFACT & 0xFFFF):
 197                debug ("Manufacturer: Intel (not supported yet)\n");
 198                info->flash_id = FLASH_MAN_INTEL;
 199                break;
 200
 201        default:
 202                printf ("Unknown Manufacturer ID: %04X\n", value);
 203                info->flash_id = FLASH_UNKNOWN;
 204                info->sector_count = 0;
 205                info->size = 0;
 206                goto out;
 207        }
 208
 209        value = addr[1];
 210        debug ("Device ID: %04X\n", value);
 211
 212        switch (addr[1]) {
 213
 214        case (AMD_ID_MIRROR & 0xFFFF):
 215                debug ("Mirror Bit flash: addr[14] = %08X  addr[15] = %08X\n",
 216                        addr[14], addr[15]);
 217
 218                switch(addr[14]) {
 219                case (AMD_ID_GL064M_2 & 0xFFFF):
 220                        if (addr[15] != (AMD_ID_GL064M_3 & 0xffff)) {
 221                                printf ("Chip: S29GLxxxM -> unknown\n");
 222                                info->flash_id = FLASH_UNKNOWN;
 223                                info->sector_count = 0;
 224                                info->size = 0;
 225                        } else {
 226                                debug ("Chip: S29GL064M-R6\n");
 227                                info->flash_id += FLASH_S29GL064M;
 228                                info->sector_count = 128;
 229                                info->size = 0x00800000;
 230                                for (i = 0; i < info->sector_count; i++) {
 231                                        info->start[i] = base;
 232                                        base += 0x10000;
 233                                }
 234                        }
 235                        break;  /* => 16 MB     */
 236                default:
 237                        printf ("Chip: *** unknown ***\n");
 238                        info->flash_id = FLASH_UNKNOWN;
 239                        info->sector_count = 0;
 240                        info->size = 0;
 241                        break;
 242                }
 243                break;
 244
 245        default:
 246                printf ("Unknown Device ID: %04X\n", value);
 247                info->flash_id = FLASH_UNKNOWN;
 248                info->sector_count = 0;
 249                info->size = 0;
 250                break;
 251        }
 252
 253out:
 254        /* Put FLASH back in read mode */
 255        flash_reset(info);
 256
 257        return (info->size);
 258}
 259
 260/*-----------------------------------------------------------------------
 261 */
 262
 263int     flash_erase (flash_info_t *info, int s_first, int s_last)
 264{
 265        vu_short *addr = (vu_short *)(info->start[0]);
 266        int flag, prot, sect, ssect, l_sect;
 267        ulong now, last;
 268
 269        debug ("flash_erase: first: %d last: %d\n", s_first, s_last);
 270
 271        if ((s_first < 0) || (s_first > s_last)) {
 272                if (info->flash_id == FLASH_UNKNOWN) {
 273                        printf ("- missing\n");
 274                } else {
 275                        printf ("- no sectors to erase\n");
 276                }
 277                return 1;
 278        }
 279
 280        if ((info->flash_id == FLASH_UNKNOWN) ||
 281            (info->flash_id > FLASH_AMD_COMP)) {
 282                printf ("Can't erase unknown flash type %08lx - aborted\n",
 283                        info->flash_id);
 284                return 1;
 285        }
 286
 287        prot = 0;
 288        for (sect=s_first; sect<=s_last; ++sect) {
 289                if (info->protect[sect]) {
 290                        prot++;
 291                }
 292        }
 293
 294        if (prot) {
 295                printf ("- Warning: %d protected sectors will not be erased!\n",
 296                        prot);
 297        } else {
 298                printf ("\n");
 299        }
 300
 301        /* Disable interrupts which might cause a timeout here */
 302        flag = disable_interrupts();
 303
 304        /*
 305         * Start erase on unprotected sectors.
 306         * Since the flash can erase multiple sectors with one command
 307         * we take advantage of that by doing the erase in chunks of
 308         * 3 sectors.
 309         */
 310        for (sect = s_first; sect <= s_last; ) {
 311                l_sect = -1;
 312
 313                addr[FLASH_CYCLE1] = 0x00AA;
 314                addr[FLASH_CYCLE2] = 0x0055;
 315                addr[FLASH_CYCLE1] = 0x0080;
 316                addr[FLASH_CYCLE1] = 0x00AA;
 317                addr[FLASH_CYCLE2] = 0x0055;
 318
 319                /* do the erase in chunks of at most 3 sectors */
 320                for (ssect = 0; ssect < 3; ssect++) {
 321                        if ((sect + ssect) > s_last)
 322                                break;
 323                        if (info->protect[sect + ssect] == 0) { /* not protected */
 324                                addr = (vu_short *)(info->start[sect + ssect]);
 325                                addr[0] = 0x0030;
 326                                l_sect = sect + ssect;
 327                        }
 328                }
 329                /* wait at least 80us - let's wait 1 ms */
 330                udelay (1000);
 331
 332                /*
 333                 * We wait for the last triggered sector
 334                 */
 335                if (l_sect < 0)
 336                        goto DONE;
 337
 338                reset_timer_masked ();
 339                last  = 0;
 340                addr = (vu_short *)(info->start[l_sect]);
 341                while ((addr[0] & 0x0080) != 0x0080) {
 342                        if ((now = get_timer_masked ()) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 343                                printf ("Timeout\n");
 344                                return 1;
 345                        }
 346                        /* show that we're waiting */
 347                        if ((now - last) > 1000) {      /* every second */
 348                                putc ('.');
 349                                last = now;
 350                        }
 351                }
 352                addr = (vu_short *)info->start[0];
 353                addr[0] = 0x00F0;       /* reset bank */
 354                sect += ssect;
 355        }
 356
 357        /* re-enable interrupts if necessary */
 358        if (flag)
 359                enable_interrupts();
 360
 361DONE:
 362        /* reset to read mode */
 363        addr = (vu_short *)info->start[0];
 364        addr[0] = 0x00F0;       /* reset bank */
 365
 366        printf (" done\n");
 367        return 0;
 368}
 369
 370/*-----------------------------------------------------------------------
 371 * Copy memory to flash, returns:
 372 * 0 - OK
 373 * 1 - write timeout
 374 * 2 - Flash not erased
 375 */
 376
 377int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 378{
 379        ulong wp, data;
 380        int rc;
 381
 382        if (addr & 1) {
 383                printf ("unaligned destination not supported\n");
 384                return ERR_ALIGN;
 385        };
 386
 387        if ((int) src & 1) {
 388                printf ("unaligned source not supported\n");
 389                return ERR_ALIGN;
 390        };
 391
 392        wp = addr;
 393
 394        while (cnt >= 2) {
 395                data = *((vu_short *)src);
 396                if ((rc = write_word_amd(info, (vu_short *)wp, data)) != 0) {
 397printf ("write_buff 1: write_word_amd() rc=%d\n", rc);
 398                        return (rc);
 399                }
 400                src += 2;
 401                wp += 2;
 402                cnt -= 2;
 403        }
 404
 405        if (cnt == 0) {
 406                return (ERR_OK);
 407        }
 408
 409        if (cnt == 1) {
 410                data = (*((volatile u8 *) src)) | (*((volatile u8 *) (wp + 1)) << 8);
 411                if ((rc = write_word_amd(info, (vu_short *)wp, data)) != 0) {
 412printf ("write_buff 1: write_word_amd() rc=%d\n", rc);
 413                        return (rc);
 414                }
 415                src += 1;
 416                wp += 1;
 417                cnt -= 1;
 418        }
 419
 420        return ERR_OK;
 421}
 422
 423/*-----------------------------------------------------------------------
 424 * Write a word to Flash for AMD FLASH
 425 * A word is 16 or 32 bits, whichever the bus width of the flash bank
 426 * (not an individual chip) is.
 427 *
 428 * returns:
 429 * 0 - OK
 430 * 1 - write timeout
 431 * 2 - Flash not erased
 432 */
 433static int write_word_amd (flash_info_t *info, vu_short *dest, ushort data)
 434{
 435        int flag;
 436        vu_short *base;         /* first address in flash bank  */
 437
 438        /* Check if Flash is (sufficiently) erased */
 439        if ((*dest & data) != data) {
 440                return (2);
 441        }
 442
 443        base = (vu_short *)(info->start[0]);
 444
 445        /* Disable interrupts which might cause a timeout here */
 446        flag = disable_interrupts();
 447
 448        base[FLASH_CYCLE1] = 0x00AA;    /* unlock */
 449        base[FLASH_CYCLE2] = 0x0055;    /* unlock */
 450        base[FLASH_CYCLE1] = 0x00A0;    /* selects program mode */
 451
 452        *dest = data;           /* start programming the data   */
 453
 454        /* re-enable interrupts if necessary */
 455        if (flag)
 456                enable_interrupts();
 457
 458        reset_timer_masked ();
 459
 460        /* data polling for D7 */
 461        while ((*dest & 0x0080) != (data & 0x0080)) {
 462                if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) {
 463                        *dest = 0x00F0; /* reset bank */
 464                        return (1);
 465                }
 466        }
 467        return (0);
 468}
 469