uboot/board/ep8260/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001, 2002
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * (C) Copyright 2002
   6 * Frank Panno <fpanno@delphintech.com>, Delphin Technology AG
   7 *
   8 * Flash Routines for AMD device AM29DL323DB on the EP8260 board.
   9 *
  10 * This file is based on board/tqm8260/flash.c.
  11 *--------------------------------------------------------------------
  12 * See file CREDITS for list of people who contributed to this
  13 * project.
  14 *
  15 * This program is free software; you can redistribute it and/or
  16 * modify it under the terms of the GNU General Public License as
  17 * published by the Free Software Foundation; either version 2 of
  18 * the License, or (at your option) any later version.
  19 *
  20 * This program is distributed in the hope that it will be useful,
  21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23 * GNU General Public License for more details.
  24 *
  25 * You should have received a copy of the GNU General Public License
  26 * along with this program; if not, write to the Free Software
  27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  28 * MA 02111-1307 USA
  29 */
  30
  31#include <common.h>
  32#include <mpc8xx.h>
  33
  34#define V_ULONG(a)      (*(volatile unsigned long *)( a ))
  35#define V_BYTE(a)       (*(volatile unsigned char *)( a ))
  36
  37
  38flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  39
  40
  41/*-----------------------------------------------------------------------
  42 */
  43void flash_reset(void)
  44{
  45        if( flash_info[0].flash_id != FLASH_UNKNOWN ) {
  46                V_ULONG( flash_info[0].start[0] ) = 0x00F000F0;
  47                V_ULONG( flash_info[0].start[0] + 4 ) = 0x00F000F0;
  48        }
  49}
  50
  51/*-----------------------------------------------------------------------
  52 */
  53ulong flash_get_size( ulong baseaddr, flash_info_t *info )
  54{
  55        short i;
  56        unsigned long flashtest_h, flashtest_l;
  57
  58        /* Write auto select command sequence and test FLASH answer */
  59        V_ULONG(baseaddr + ((ulong)0x0555 << 3)) = 0x00AA00AA;
  60        V_ULONG(baseaddr + ((ulong)0x02AA << 3)) = 0x00550055;
  61        V_ULONG(baseaddr + ((ulong)0x0555 << 3)) = 0x00900090;
  62        V_ULONG(baseaddr + 4 + ((ulong)0x0555 << 3)) = 0x00AA00AA;
  63        V_ULONG(baseaddr + 4 + ((ulong)0x02AA << 3)) = 0x00550055;
  64        V_ULONG(baseaddr + 4 + ((ulong)0x0555 << 3)) = 0x00900090;
  65
  66        flashtest_h = V_ULONG(baseaddr);                /* manufacturer ID         */
  67        flashtest_l = V_ULONG(baseaddr + 4);
  68
  69        if ((int)flashtest_h == AMD_MANUFACT) {
  70                info->flash_id = FLASH_MAN_AMD;
  71        } else {
  72                info->flash_id = FLASH_UNKNOWN;
  73                info->sector_count = 0;
  74                info->size = 0;
  75                return (0);                             /* no or unknown flash     */
  76        }
  77
  78        flashtest_h = V_ULONG(baseaddr + 8);            /* device ID               */
  79        flashtest_l = V_ULONG(baseaddr + 12);
  80        if (flashtest_h != flashtest_l) {
  81                info->flash_id = FLASH_UNKNOWN;
  82                return(0);
  83        }
  84
  85        switch((int)flashtest_h) {
  86        case AMD_ID_DL323B:
  87                info->flash_id += FLASH_AMDL323B;
  88                info->sector_count = 71;
  89                info->size = 0x01000000;         /* 4 * 4 MB = 16 MB    */
  90                break;
  91        case AMD_ID_LV640U:     /* AMDLV640 and AMDLV641 have same ID */
  92                info->flash_id += FLASH_AMLV640U;
  93                info->sector_count = 128;
  94                info->size = 0x02000000;        /* 4 * 8 MB = 32 MB     */
  95                break;
  96        default:
  97                info->flash_id = FLASH_UNKNOWN;
  98                return(0);                              /* no or unknown flash     */
  99        }
 100
 101        if(flashtest_h == AMD_ID_LV640U) {
 102                /* set up sector start adress table (uniform sector type) */
 103                for (i = 0; i < info->sector_count; i++)
 104                        info->start[i] = baseaddr + (i * 0x00040000);
 105        } else {
 106                /* set up sector start adress table (bottom sector type) */
 107                for (i = 0; i < 8; i++) {
 108                        info->start[i] = baseaddr + (i * 0x00008000);
 109                }
 110                for (i = 8; i < info->sector_count; i++) {
 111                        info->start[i] = baseaddr + (i * 0x00040000) - 0x001C0000;
 112                }
 113        }
 114        /* check for protected sectors */
 115        for (i = 0; i < info->sector_count; i++) {
 116                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 117                if ((V_ULONG( info->start[i] + 16 ) & 0x00010001) ||
 118                    (V_ULONG( info->start[i] + 20 ) & 0x00010001)) {
 119                        info->protect[i] = 1;           /* D0 = 1 if protected */
 120                } else {
 121                        info->protect[i] = 0;
 122                }
 123        }
 124
 125        flash_reset();
 126        return(info->size);
 127}
 128
 129/*-----------------------------------------------------------------------
 130 */
 131unsigned long flash_init (void)
 132{
 133        unsigned long size_b0 = 0;
 134        int i;
 135
 136        /* Init: no FLASHes known */
 137        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
 138                flash_info[i].flash_id = FLASH_UNKNOWN;
 139        }
 140
 141        /* Static FLASH Bank configuration here (only one bank) */
 142
 143        size_b0 = flash_get_size(CONFIG_SYS_FLASH0_BASE, &flash_info[0]);
 144        if (flash_info[0].flash_id == FLASH_UNKNOWN || size_b0 == 0) {
 145                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
 146                        size_b0, size_b0>>20);
 147        }
 148
 149        /*
 150         * protect monitor and environment sectors
 151         */
 152
 153#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH0_BASE
 154        flash_protect(FLAG_PROTECT_SET,
 155                      CONFIG_SYS_MONITOR_BASE,
 156                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
 157                      &flash_info[0]);
 158#endif
 159
 160#if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
 161# ifndef  CONFIG_ENV_SIZE
 162#  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
 163# endif
 164        flash_protect(FLAG_PROTECT_SET,
 165                      CONFIG_ENV_ADDR,
 166                      CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
 167                      &flash_info[0]);
 168#endif
 169
 170        return (size_b0);
 171}
 172
 173/*-----------------------------------------------------------------------
 174 */
 175void flash_print_info  (flash_info_t *info)
 176{
 177        int i;
 178
 179        if (info->flash_id == FLASH_UNKNOWN) {
 180                printf ("missing or unknown FLASH type\n");
 181                return;
 182        }
 183
 184        switch ((info->flash_id >> 16) & 0xff) {
 185        case FLASH_MAN_AMD:         printf ("AMD ");                break;
 186        default:                    printf ("Unknown Vendor ");     break;
 187        }
 188
 189        switch (info->flash_id & FLASH_TYPEMASK) {
 190        case FLASH_AMDL323B:    printf ("29DL323B (32 M, bottom sector)\n");
 191                                break;
 192        case FLASH_AMLV640U:    printf ("29LV640U (64 M, uniform sector)\n");
 193                                break;
 194        default:                printf ("Unknown Chip Type\n");
 195                                break;
 196        }
 197
 198        printf ("  Size: %ld MB in %d Sectors\n",
 199                info->size >> 20, info->sector_count);
 200
 201        printf ("  Sector Start Addresses:");
 202        for (i=0; i<info->sector_count; ++i) {
 203                if ((i % 5) == 0)
 204                        printf ("\n   ");
 205                printf (" %08lX%s",
 206                        info->start[i],
 207                        info->protect[i] ? " (RO)" : "     "
 208                        );
 209        }
 210        printf ("\n");
 211        return;
 212}
 213
 214/*-----------------------------------------------------------------------
 215 */
 216int flash_erase (flash_info_t *info, int s_first, int s_last)
 217{
 218        int flag, prot, sect, l_sect;
 219        ulong start, now, last;
 220
 221        if ((s_first < 0) || (s_first > s_last)) {
 222                if (info->flash_id == FLASH_UNKNOWN) {
 223                        printf ("- missing\n");
 224                } else {
 225                        printf ("- no sectors to erase\n");
 226                }
 227                return 1;
 228        }
 229
 230        prot = 0;
 231        for (sect = s_first; sect <= s_last; sect++) {
 232                if (info->protect[sect])
 233                        prot++;
 234        }
 235
 236        if (prot) {
 237                printf ("- Warning: %d protected sectors will not be erased!\n",
 238                        prot);
 239        } else {
 240                printf ("\n");
 241        }
 242
 243        l_sect = -1;
 244
 245        /* Disable interrupts which might cause a timeout here */
 246        flag = disable_interrupts();
 247
 248        V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
 249        V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
 250        V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00800080;
 251        V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
 252        V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
 253        V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
 254        V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
 255        V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00800080;
 256        V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
 257        V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
 258        udelay (1000);
 259
 260        /* Start erase on unprotected sectors */
 261        for (sect = s_first; sect<=s_last; sect++) {
 262                if (info->protect[sect] == 0) { /* not protected */
 263                        V_ULONG( info->start[sect] ) = 0x00300030;
 264                        V_ULONG( info->start[sect] + 4 ) = 0x00300030;
 265                        l_sect = sect;
 266                }
 267        }
 268
 269        /* re-enable interrupts if necessary */
 270        if (flag)
 271                enable_interrupts();
 272
 273        /* wait at least 80us - let's wait 1 ms */
 274        udelay (1000);
 275
 276        /*
 277         * We wait for the last triggered sector
 278         */
 279        if (l_sect < 0)
 280                goto DONE;
 281
 282        start = get_timer (0);
 283        last  = start;
 284        while ((V_ULONG( info->start[l_sect] ) & 0x00800080) != 0x00800080 ||
 285               (V_ULONG( info->start[l_sect] + 4 ) & 0x00800080) != 0x00800080)
 286        {
 287                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 288                        printf ("Timeout\n");
 289                        return 1;
 290                }
 291                /* show that we're waiting */
 292                if ((now - last) > 1000) {      /* every second */
 293                        serial_putc ('.');
 294                        last = now;
 295                }
 296        }
 297
 298 DONE:
 299        /* reset to read mode */
 300        flash_reset ();
 301
 302        printf (" done\n");
 303        return 0;
 304}
 305
 306static int write_dword (flash_info_t *, ulong, unsigned char *);
 307
 308/*-----------------------------------------------------------------------
 309 * Copy memory to flash, returns:
 310 * 0 - OK
 311 * 1 - write timeout
 312 * 2 - Flash not erased
 313 */
 314
 315int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 316{
 317        ulong dp;
 318        static unsigned char bb[8];
 319        int i, l, rc, cc = cnt;
 320
 321        dp = (addr & ~7);       /* get lower dword aligned address */
 322
 323        /*
 324         * handle unaligned start bytes
 325         */
 326        if ((l = addr - dp) != 0) {
 327                for (i = 0; i < 8; i++)
 328                        bb[i] = (i < l || (i-l) >= cc) ? V_BYTE(dp+i) : *src++;
 329                if ((rc = write_dword(info, dp, bb)) != 0)
 330                {
 331                        return (rc);
 332                }
 333                dp += 8;
 334                cc -= 8 - l;
 335        }
 336
 337        /*
 338         * handle word aligned part
 339         */
 340        while (cc >= 8) {
 341                if ((rc = write_dword(info, dp, src)) != 0) {
 342                        return (rc);
 343                }
 344                dp  += 8;
 345                src += 8;
 346                cc -= 8;
 347        }
 348
 349        if (cc <= 0) {
 350                return (0);
 351        }
 352
 353        /*
 354         * handle unaligned tail bytes
 355         */
 356        for (i = 0; i < 8; i++) {
 357                bb[i] = (i < cc) ? *src++ : V_BYTE(dp+i);
 358        }
 359        return (write_dword(info, dp, bb));
 360}
 361
 362/*-----------------------------------------------------------------------
 363 * Write a dword to Flash, returns:
 364 * 0 - OK
 365 * 1 - write timeout
 366 * 2 - Flash not erased
 367 */
 368static int write_dword (flash_info_t *info, ulong dest, unsigned char * pdata)
 369{
 370        ulong start;
 371        ulong cl = 0, ch =0;
 372        int flag, i;
 373
 374        for (ch=0, i=0; i < 4; i++)
 375                ch = (ch << 8) + *pdata++;      /* high word    */
 376        for (cl=0, i=0; i < 4; i++)
 377                cl = (cl << 8) + *pdata++;      /* low word     */
 378
 379        /* Check if Flash is (sufficiently) erased */
 380        if ((*((vu_long *)dest) & ch)   != ch
 381            ||(*((vu_long *)(dest + 4)) & cl)   != cl)
 382        {
 383                return (2);
 384        }
 385
 386        /* Disable interrupts which might cause a timeout here */
 387        flag = disable_interrupts();
 388
 389        V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
 390        V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
 391        V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00A000A0;
 392        V_ULONG( dest ) = ch;
 393        V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
 394        V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
 395        V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00A000A0;
 396        V_ULONG( dest + 4 ) = cl;
 397
 398        /* re-enable interrupts if necessary */
 399        if (flag)
 400                enable_interrupts();
 401
 402        /* data polling for D7 */
 403        start = get_timer (0);
 404        while (((V_ULONG( dest ) & 0x00800080) != (ch & 0x00800080)) ||
 405               ((V_ULONG( dest + 4 ) & 0x00800080) != (cl & 0x00800080))) {
 406                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 407                        return (1);
 408                }
 409        }
 410        return (0);
 411}
 412