uboot/board/LEOX/elpt860/flash.c
<<
>>
Prefs
   1/*
   2**=====================================================================
   3**
   4** Copyright (C) 2000, 2001, 2002, 2003
   5** The LEOX team <team@leox.org>, http://www.leox.org
   6**
   7** LEOX.org is about the development of free hardware and software resources
   8**   for system on chip.
   9**
  10** Description: U-Boot port on the LEOX's ELPT860 CPU board
  11** ~~~~~~~~~~~
  12**
  13**=====================================================================
  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*/
  32
  33/*
  34** Note 1: In this file, you have to provide the following variable:
  35** ------
  36**              flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]
  37** 'flash_info_t' structure is defined into 'include/flash.h'
  38** and defined as extern into 'common/cmd_flash.c'
  39**
  40** Note 2: In this file, you have to provide the following functions:
  41** ------
  42**              unsigned long   flash_init(void)
  43** called from 'board_init_r()' into 'common/board.c'
  44**
  45**              void            flash_print_info(flash_info_t *info)
  46** called from 'do_flinfo()' into 'common/cmd_flash.c'
  47**
  48**              int             flash_erase(flash_info_t *info,
  49**                                          int           s_first,
  50**                                          int           s_last)
  51** called from 'do_flerase()' & 'flash_sect_erase()' into 'common/cmd_flash.c'
  52**
  53**              int             write_buff (flash_info_t *info,
  54**                                          uchar        *src,
  55**                                          ulong         addr,
  56**                                          ulong         cnt)
  57** called from 'flash_write()' into 'common/cmd_flash.c'
  58*/
  59
  60#include <common.h>
  61#include <mpc8xx.h>
  62
  63
  64#ifndef CONFIG_ENV_ADDR
  65#  define CONFIG_ENV_ADDR       (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET)
  66#endif
  67
  68flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  69
  70/*-----------------------------------------------------------------------
  71 * Internal Functions
  72 */
  73static void   flash_get_offsets (ulong base, flash_info_t *info);
  74static ulong  flash_get_size (volatile unsigned char *addr, flash_info_t *info);
  75
  76static int write_word (flash_info_t *info, ulong dest, ulong data);
  77static int write_byte (flash_info_t *info, ulong dest, uchar data);
  78
  79/*-----------------------------------------------------------------------
  80 */
  81
  82unsigned long
  83flash_init (void)
  84{
  85  volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR;
  86  volatile memctl8xx_t *memctl = &immap->im_memctl;
  87  unsigned long         size_b0;
  88  int i;
  89
  90  /* Init: no FLASHes known */
  91  for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i)
  92    {
  93      flash_info[i].flash_id = FLASH_UNKNOWN;
  94    }
  95
  96  /* Static FLASH Bank configuration here - FIXME XXX */
  97
  98  size_b0 = flash_get_size ((volatile unsigned char *)FLASH_BASE0_PRELIM,
  99                            &flash_info[0]);
 100
 101  if ( flash_info[0].flash_id == FLASH_UNKNOWN )
 102    {
 103      printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
 104              size_b0, size_b0<<20);
 105    }
 106
 107  /* Remap FLASH according to real size */
 108  memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK);
 109  memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_PS_8 | BR_V;
 110
 111  /* Re-do sizing to get full correct info */
 112  size_b0 = flash_get_size ((volatile unsigned char *)CONFIG_SYS_FLASH_BASE,
 113                            &flash_info[0]);
 114
 115  flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
 116
 117#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
 118  /* monitor protection ON by default */
 119  flash_protect (FLAG_PROTECT_SET,
 120                 CONFIG_SYS_MONITOR_BASE,
 121                 CONFIG_SYS_MONITOR_BASE + monitor_flash_len-1,
 122                 &flash_info[0]);
 123#endif
 124
 125#ifdef  CONFIG_ENV_IS_IN_FLASH
 126  /* ENV protection ON by default */
 127  flash_protect(FLAG_PROTECT_SET,
 128                CONFIG_ENV_ADDR,
 129                CONFIG_ENV_ADDR + CONFIG_ENV_SIZE-1,
 130                &flash_info[0]);
 131#endif
 132
 133  flash_info[0].size = size_b0;
 134
 135  return (size_b0);
 136}
 137
 138/*-----------------------------------------------------------------------
 139 */
 140static void
 141flash_get_offsets (ulong          base,
 142                   flash_info_t  *info)
 143{
 144  int i;
 145
 146#define SECTOR_64KB    0x00010000
 147
 148  /* set up sector start adress table */
 149  for (i = 0; i < info->sector_count; i++)
 150    {
 151      info->start[i] = base + (i * SECTOR_64KB);
 152    }
 153}
 154
 155/*-----------------------------------------------------------------------
 156 */
 157void
 158flash_print_info (flash_info_t *info)
 159{
 160  int i;
 161
 162  if ( info->flash_id == FLASH_UNKNOWN )
 163    {
 164      printf ("missing or unknown FLASH type\n");
 165      return;
 166    }
 167
 168  switch ( info->flash_id & FLASH_VENDMASK )
 169    {
 170    case FLASH_MAN_AMD: printf ("AMD ");                break;
 171    case FLASH_MAN_FUJ: printf ("FUJITSU ");            break;
 172    case FLASH_MAN_STM: printf ("STM (Thomson) ");      break;
 173    default:            printf ("Unknown Vendor ");     break;
 174    }
 175
 176  switch ( info->flash_id & FLASH_TYPEMASK )
 177    {
 178    case FLASH_AM040:   printf ("AM29F040   (4 Mbits)\n");
 179      break;
 180    default:            printf ("Unknown Chip Type\n");
 181      break;
 182    }
 183
 184  printf ("  Size: %ld KB in %d Sectors\n",
 185          info->size >> 10, info->sector_count);
 186
 187  printf ("  Sector Start Addresses:");
 188  for (i=0; i<info->sector_count; ++i)
 189    {
 190      if ((i % 5) == 0)
 191        printf ("\n   ");
 192      printf (" %08lX%s",
 193              info->start[i],
 194              info->protect[i] ? " (RO)" : "     "
 195              );
 196    }
 197  printf ("\n");
 198
 199  return;
 200}
 201
 202/*-----------------------------------------------------------------------
 203 */
 204
 205
 206/*-----------------------------------------------------------------------
 207 */
 208
 209/*
 210 * The following code cannot be run from FLASH!
 211 */
 212
 213static ulong
 214flash_get_size (volatile unsigned char *addr,
 215                flash_info_t           *info)
 216{
 217  short i;
 218  uchar value;
 219  ulong base = (ulong)addr;
 220
 221  /* Write auto select command: read Manufacturer ID */
 222  addr[0x0555] = 0xAA;
 223  addr[0x02AA] = 0x55;
 224  addr[0x0555] = 0x90;
 225
 226  value = addr[0];
 227
 228  switch ( value )
 229    {
 230      /*    case AMD_MANUFACT: */
 231    case 0x01:
 232      info->flash_id = FLASH_MAN_AMD;
 233      break;
 234      /*    case FUJ_MANUFACT: */
 235    case 0x04:
 236      info->flash_id = FLASH_MAN_FUJ;
 237      break;
 238      /*    case STM_MANUFACT: */
 239    case 0x20:
 240      info->flash_id = FLASH_MAN_STM;
 241      break;
 242
 243    default:
 244      info->flash_id = FLASH_UNKNOWN;
 245      info->sector_count = 0;
 246      info->size = 0;
 247      return (0);                       /* no or unknown flash  */
 248    }
 249
 250  value = addr[1];                      /* device ID            */
 251
 252  switch ( value )
 253    {
 254    case STM_ID_F040B:
 255    case AMD_ID_F040B:
 256      info->flash_id += FLASH_AM040;    /* 4 Mbits = 512k * 8  */
 257      info->sector_count = 8;
 258      info->size = 0x00080000;
 259      break;
 260
 261    default:
 262      info->flash_id = FLASH_UNKNOWN;
 263      return (0);                       /* => no or unknown flash */
 264    }
 265
 266  /* set up sector start adress table */
 267  for (i = 0; i < info->sector_count; i++)
 268    {
 269      info->start[i] = base + (i * 0x00010000);
 270    }
 271
 272  /* check for protected sectors */
 273  for (i = 0; i < info->sector_count; i++)
 274    {
 275      /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 276      /* D0 = 1 if protected */
 277      addr = (volatile unsigned char *)(info->start[i]);
 278      info->protect[i] = addr[2] & 1;
 279    }
 280
 281  /*
 282   * Prevent writes to uninitialized FLASH.
 283   */
 284  if ( info->flash_id != FLASH_UNKNOWN )
 285    {
 286      addr = (volatile unsigned char *)info->start[0];
 287
 288      *addr = 0xF0;     /* reset bank */
 289    }
 290
 291  return (info->size);
 292}
 293
 294
 295/*-----------------------------------------------------------------------
 296 */
 297
 298int
 299flash_erase (flash_info_t  *info,
 300             int            s_first,
 301             int            s_last)
 302{
 303  volatile unsigned char *addr = (volatile unsigned char *)(info->start[0]);
 304  int flag, prot, sect, l_sect;
 305  ulong start, now, last;
 306
 307  if ( (s_first < 0) || (s_first > s_last) )
 308    {
 309      if ( info->flash_id == FLASH_UNKNOWN )
 310        {
 311          printf ("- missing\n");
 312        }
 313      else
 314        {
 315          printf ("- no sectors to erase\n");
 316        }
 317      return ( 1 );
 318    }
 319
 320  if ( (info->flash_id == FLASH_UNKNOWN) ||
 321       (info->flash_id > FLASH_AMD_COMP) )
 322    {
 323      printf ("Can't erase unknown flash type %08lx - aborted\n",
 324              info->flash_id);
 325      return ( 1 );
 326    }
 327
 328  prot = 0;
 329  for (sect=s_first; sect<=s_last; ++sect)
 330    {
 331      if ( info->protect[sect] )
 332        {
 333          prot++;
 334        }
 335    }
 336
 337  if ( prot )
 338    {
 339      printf ("- Warning: %d protected sectors will not be erased!\n", prot);
 340    }
 341  else
 342    {
 343      printf ("\n");
 344    }
 345
 346  l_sect = -1;
 347
 348  /* Disable interrupts which might cause a timeout here */
 349  flag = disable_interrupts();
 350
 351  addr[0x0555] = 0xAA;
 352  addr[0x02AA] = 0x55;
 353  addr[0x0555] = 0x80;
 354  addr[0x0555] = 0xAA;
 355  addr[0x02AA] = 0x55;
 356
 357  /* Start erase on unprotected sectors */
 358  for (sect = s_first; sect<=s_last; sect++)
 359    {
 360      if (info->protect[sect] == 0)    /* not protected */
 361        {
 362          addr = (volatile unsigned char *)(info->start[sect]);
 363          addr[0] = 0x30;
 364          l_sect = sect;
 365        }
 366    }
 367
 368  /* re-enable interrupts if necessary */
 369  if ( flag )
 370    enable_interrupts();
 371
 372  /* wait at least 80us - let's wait 1 ms */
 373  udelay (1000);
 374
 375  /*
 376   * We wait for the last triggered sector
 377   */
 378  if ( l_sect < 0 )
 379    goto DONE;
 380
 381  start = get_timer (0);
 382  last  = start;
 383  addr = (volatile unsigned char *)(info->start[l_sect]);
 384  while ( (addr[0] & 0x80) != 0x80 )
 385    {
 386      if ( (now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT )
 387        {
 388          printf ("Timeout\n");
 389          return ( 1 );
 390        }
 391      /* show that we're waiting */
 392      if ( (now - last) > 1000 )     /* every second */
 393        {
 394          putc ('.');
 395          last = now;
 396        }
 397    }
 398
 399DONE:
 400  /* reset to read mode */
 401  addr = (volatile unsigned char *)info->start[0];
 402  addr[0] = 0xF0;       /* reset bank */
 403
 404  printf (" done\n");
 405
 406  return ( 0 );
 407}
 408
 409/*-----------------------------------------------------------------------
 410 * Copy memory to flash, returns:
 411 * 0 - OK
 412 * 1 - write timeout
 413 * 2 - Flash not erased
 414 */
 415
 416int
 417write_buff (flash_info_t  *info,
 418            uchar         *src,
 419            ulong          addr,
 420            ulong          cnt)
 421{
 422  ulong cp, wp, data;
 423  uchar bdata;
 424  int i, l, rc;
 425
 426  if ( (info->flash_id & FLASH_TYPEMASK) == FLASH_AM040 )
 427    {
 428      /* Width of the data bus: 8 bits */
 429
 430      wp = addr;
 431
 432      while ( cnt )
 433        {
 434          bdata = *src++;
 435
 436          if ( (rc = write_byte(info, wp, bdata)) != 0 )
 437            {
 438              return (rc);
 439            }
 440
 441          ++wp;
 442          --cnt;
 443        }
 444
 445      return ( 0 );
 446    }
 447  else
 448    {
 449      /* Width of the data bus: 32 bits */
 450
 451      wp = (addr & ~3); /* get lower word aligned address */
 452
 453      /*
 454       * handle unaligned start bytes
 455       */
 456      if ( (l = addr - wp) != 0 )
 457        {
 458          data = 0;
 459          for (i=0, cp=wp; i<l; ++i, ++cp)
 460            {
 461              data = (data << 8) | (*(uchar *)cp);
 462            }
 463          for (; i<4 && cnt>0; ++i)
 464            {
 465              data = (data << 8) | *src++;
 466              --cnt;
 467              ++cp;
 468            }
 469          for (; cnt==0 && i<4; ++i, ++cp)
 470            {
 471              data = (data << 8) | (*(uchar *)cp);
 472            }
 473
 474          if ( (rc = write_word(info, wp, data)) != 0 )
 475            {
 476              return (rc);
 477            }
 478          wp += 4;
 479        }
 480
 481      /*
 482       * handle word aligned part
 483       */
 484      while ( cnt >= 4 )
 485        {
 486          data = 0;
 487          for (i=0; i<4; ++i)
 488            {
 489              data = (data << 8) | *src++;
 490            }
 491          if ( (rc = write_word(info, wp, data)) != 0 )
 492            {
 493              return (rc);
 494            }
 495          wp  += 4;
 496          cnt -= 4;
 497        }
 498
 499      if ( cnt == 0 )
 500        {
 501          return (0);
 502        }
 503
 504      /*
 505       * handle unaligned tail bytes
 506       */
 507      data = 0;
 508      for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp)
 509        {
 510          data = (data << 8) | *src++;
 511          --cnt;
 512        }
 513      for (; i<4; ++i, ++cp)
 514        {
 515          data = (data << 8) | (*(uchar *)cp);
 516        }
 517
 518      return (write_word(info, wp, data));
 519    }
 520}
 521
 522/*-----------------------------------------------------------------------
 523 * Write a word to Flash, returns:
 524 * 0 - OK
 525 * 1 - write timeout
 526 * 2 - Flash not erased
 527 */
 528static int
 529write_word (flash_info_t  *info,
 530            ulong          dest,
 531            ulong          data)
 532{
 533  vu_long *addr = (vu_long*)(info->start[0]);
 534  ulong start;
 535  int flag;
 536
 537  /* Check if Flash is (sufficiently) erased */
 538  if ( (*((vu_long *)dest) & data) != data )
 539    {
 540      return (2);
 541    }
 542  /* Disable interrupts which might cause a timeout here */
 543  flag = disable_interrupts();
 544
 545  addr[0x0555] = 0x00AA00AA;
 546  addr[0x02AA] = 0x00550055;
 547  addr[0x0555] = 0x00A000A0;
 548
 549  *((vu_long *)dest) = data;
 550
 551  /* re-enable interrupts if necessary */
 552  if ( flag )
 553    enable_interrupts();
 554
 555  /* data polling for D7 */
 556  start = get_timer (0);
 557  while ( (*((vu_long *)dest) & 0x00800080) != (data & 0x00800080) )
 558    {
 559      if ( get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT )
 560        {
 561          return (1);
 562        }
 563    }
 564
 565  return (0);
 566}
 567
 568/*-----------------------------------------------------------------------
 569 * Write a byte to Flash, returns:
 570 * 0 - OK
 571 * 1 - write timeout
 572 * 2 - Flash not erased
 573 */
 574static int
 575write_byte (flash_info_t  *info,
 576            ulong          dest,
 577            uchar          data)
 578{
 579  volatile unsigned char *addr = (volatile unsigned char *)(info->start[0]);
 580  ulong  start;
 581  int    flag;
 582
 583  /* Check if Flash is (sufficiently) erased */
 584  if ( (*((volatile unsigned char *)dest) & data) != data )
 585    {
 586      return (2);
 587    }
 588  /* Disable interrupts which might cause a timeout here */
 589  flag = disable_interrupts();
 590
 591  addr[0x0555] = 0xAA;
 592  addr[0x02AA] = 0x55;
 593  addr[0x0555] = 0xA0;
 594
 595  *((volatile unsigned char *)dest) = data;
 596
 597  /* re-enable interrupts if necessary */
 598  if ( flag )
 599    enable_interrupts();
 600
 601  /* data polling for D7 */
 602  start = get_timer (0);
 603  while ( (*((volatile unsigned char *)dest) & 0x80) != (data & 0x80) )
 604    {
 605      if ( get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT )
 606        {
 607          return (1);
 608        }
 609    }
 610
 611  return (0);
 612}
 613
 614/*-----------------------------------------------------------------------
 615 */
 616