uboot/board/RPXlite/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24/*
  25 * Yoo. Jonghoon, IPone, yooth@ipone.co.kr
  26 * U-Boot port on RPXlite board
  27 *
  28 * Some of flash control words are modified. (from 2x16bit device
  29 * to 4x8bit device)
  30 * RPXLite board I tested has only 4 AM29LV800BB devices. Other devices
  31 * are not tested.
  32 *
  33 * (?) Does an RPXLite board which
  34 *      does not use AM29LV800 flash memory exist ?
  35 *      I don't know...
  36 */
  37
  38#include <common.h>
  39#include <mpc8xx.h>
  40
  41flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  42
  43/*-----------------------------------------------------------------------
  44 * Functions
  45 */
  46static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  47static int write_word (flash_info_t *info, ulong dest, ulong data);
  48static void flash_get_offsets (ulong base, flash_info_t *info);
  49
  50/*-----------------------------------------------------------------------
  51 */
  52
  53unsigned long flash_init (void)
  54{
  55/*      volatile immap_t     *immap  = (immap_t *)CONFIG_SYS_IMMR; */
  56/*      volatile memctl8xx_t *memctl = &immap->im_memctl; */
  57        unsigned long size_b0 ;
  58        int i;
  59
  60        /* Init: no FLASHes known */
  61        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  62                flash_info[i].flash_id = FLASH_UNKNOWN;
  63        }
  64
  65        /* Static FLASH Bank configuration here - FIXME XXX */
  66/*
  67        size_b0 = flash_get_size((vu_long *)FLASH_BASE_DEBUG, &flash_info[0]);
  68
  69        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
  70                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
  71                        size_b0, size_b0<<20);
  72        }
  73*/
  74        /* Remap FLASH according to real size */
  75/*%%%
  76        memctl->memc_or0 = CONFIG_SYS_OR_TIMING_FLASH | (-size_b0 & 0xFFFF8000);
  77        memctl->memc_br0 = (CONFIG_SYS_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V;
  78%%%*/
  79        /* Re-do sizing to get full correct info */
  80
  81        size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  82        flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  83
  84#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  85        /* monitor protection ON by default */
  86        flash_protect(FLAG_PROTECT_SET,
  87                      CONFIG_SYS_MONITOR_BASE,
  88                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  89                      &flash_info[0]);
  90#endif
  91
  92        flash_info[0].size = size_b0;
  93
  94        return (size_b0);
  95}
  96
  97/*-----------------------------------------------------------------------
  98 */
  99static void flash_get_offsets (ulong base, flash_info_t *info)
 100{
 101        int i;
 102
 103        /* set up sector start address table */
 104        if (info->flash_id & FLASH_BTYPE) {
 105                /* set sector offsets for bottom boot block type        */
 106                info->start[0] = base + 0x00000000;
 107                info->start[1] = base + 0x00010000;
 108                info->start[2] = base + 0x00018000;
 109                info->start[3] = base + 0x00020000;
 110                for (i = 4; i < info->sector_count; i++) {
 111                        info->start[i] = base + ((i-3) * 0x00040000) ;
 112                }
 113        } else {
 114                /* set sector offsets for top boot block type           */
 115                i = info->sector_count - 1;
 116                info->start[i--] = base + info->size - 0x00010000;
 117                info->start[i--] = base + info->size - 0x00018000;
 118                info->start[i--] = base + info->size - 0x00020000;
 119                for (; i >= 0; i--) {
 120                        info->start[i] = base + i * 0x00040000;
 121                }
 122        }
 123
 124}
 125
 126/*-----------------------------------------------------------------------
 127 */
 128void flash_print_info  (flash_info_t *info)
 129{
 130        int i;
 131
 132        if (info->flash_id == FLASH_UNKNOWN) {
 133                printf ("missing or unknown FLASH type\n");
 134                return;
 135        }
 136
 137        switch (info->flash_id & FLASH_VENDMASK) {
 138        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 139        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
 140        default:                printf ("Unknown Vendor ");     break;
 141        }
 142
 143        switch (info->flash_id & FLASH_TYPEMASK) {
 144        case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
 145                                break;
 146        case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
 147                                break;
 148        case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
 149                                break;
 150        case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
 151                                break;
 152        case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
 153                                break;
 154        case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
 155                                break;
 156        case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
 157                                break;
 158        case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
 159                                break;
 160        default:                printf ("Unknown Chip Type\n");
 161                                break;
 162        }
 163
 164        printf ("  Size: %ld MB in %d Sectors\n",
 165                info->size >> 20, info->sector_count);
 166
 167        printf ("  Sector Start Addresses:");
 168        for (i=0; i<info->sector_count; ++i) {
 169                if ((i % 5) == 0)
 170                        printf ("\n   ");
 171                printf (" %08lX%s",
 172                        info->start[i],
 173                        info->protect[i] ? " (RO)" : "     "
 174                );
 175        }
 176        printf ("\n");
 177        return;
 178}
 179
 180/*-----------------------------------------------------------------------
 181 */
 182
 183
 184/*-----------------------------------------------------------------------
 185 */
 186
 187/*
 188 * The following code cannot be run from FLASH!
 189 */
 190
 191static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 192{
 193        short i;
 194        ulong value;
 195        ulong base = (ulong)addr;
 196
 197        /* Write auto select command: read Manufacturer ID */
 198        addr[0xAAA] = 0x00AA00AA ;
 199        addr[0x555] = 0x00550055 ;
 200        addr[0xAAA] = 0x00900090 ;
 201
 202        value = addr[0] ;
 203
 204        switch (value & 0x00FF00FF) {
 205        case AMD_MANUFACT:
 206                info->flash_id = FLASH_MAN_AMD;
 207                break;
 208        case FUJ_MANUFACT:
 209                info->flash_id = FLASH_MAN_FUJ;
 210                break;
 211        default:
 212                info->flash_id = FLASH_UNKNOWN;
 213                info->sector_count = 0;
 214                info->size = 0;
 215                return (0);                     /* no or unknown flash  */
 216        }
 217
 218        value = addr[2] ;               /* device ID            */
 219
 220        switch (value & 0x00FF00FF) {
 221        case (AMD_ID_LV400T & 0x00FF00FF):
 222                info->flash_id += FLASH_AM400T;
 223                info->sector_count = 11;
 224                info->size = 0x00100000;
 225                break;                          /* => 1 MB              */
 226
 227        case (AMD_ID_LV400B & 0x00FF00FF):
 228                info->flash_id += FLASH_AM400B;
 229                info->sector_count = 11;
 230                info->size = 0x00100000;
 231                break;                          /* => 1 MB              */
 232
 233        case (AMD_ID_LV800T & 0x00FF00FF):
 234                info->flash_id += FLASH_AM800T;
 235                info->sector_count = 19;
 236                info->size = 0x00200000;
 237                break;                          /* => 2 MB              */
 238
 239        case (AMD_ID_LV800B & 0x00FF00FF):
 240                info->flash_id += FLASH_AM800B;
 241                info->sector_count = 19;
 242                info->size = 0x00400000;        /*%%% Size doubled by yooth */
 243                break;                          /* => 4 MB              */
 244
 245        case (AMD_ID_LV160T & 0x00FF00FF):
 246                info->flash_id += FLASH_AM160T;
 247                info->sector_count = 35;
 248                info->size = 0x00400000;
 249                break;                          /* => 4 MB              */
 250
 251        case (AMD_ID_LV160B & 0x00FF00FF):
 252                info->flash_id += FLASH_AM160B;
 253                info->sector_count = 35;
 254                info->size = 0x00400000;
 255                break;                          /* => 4 MB              */
 256#if 0   /* enable when device IDs are available */
 257        case AMD_ID_LV320T:
 258                info->flash_id += FLASH_AM320T;
 259                info->sector_count = 67;
 260                info->size = 0x00800000;
 261                break;                          /* => 8 MB              */
 262
 263        case AMD_ID_LV320B:
 264                info->flash_id += FLASH_AM320B;
 265                info->sector_count = 67;
 266                info->size = 0x00800000;
 267                break;                          /* => 8 MB              */
 268#endif
 269        default:
 270                info->flash_id = FLASH_UNKNOWN;
 271                return (0);                     /* => no or unknown flash */
 272
 273        }
 274        /*%%% sector start address modified */
 275        /* set up sector start address table */
 276        if (info->flash_id & FLASH_BTYPE) {
 277                /* set sector offsets for bottom boot block type        */
 278                info->start[0] = base + 0x00000000;
 279                info->start[1] = base + 0x00010000;
 280                info->start[2] = base + 0x00018000;
 281                info->start[3] = base + 0x00020000;
 282                for (i = 4; i < info->sector_count; i++) {
 283                        info->start[i] = base + ((i-3) * 0x00040000) ;
 284                }
 285        } else {
 286                /* set sector offsets for top boot block type           */
 287                i = info->sector_count - 1;
 288                info->start[i--] = base + info->size - 0x00010000;
 289                info->start[i--] = base + info->size - 0x00018000;
 290                info->start[i--] = base + info->size - 0x00020000;
 291                for (; i >= 0; i--) {
 292                        info->start[i] = base + i * 0x00040000;
 293                }
 294        }
 295
 296        /* check for protected sectors */
 297        for (i = 0; i < info->sector_count; i++) {
 298                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 299                /* D0 = 1 if protected */
 300                addr = (volatile unsigned long *)(info->start[i]);
 301                info->protect[i] = addr[4] & 1 ;
 302        }
 303
 304        /*
 305         * Prevent writes to uninitialized FLASH.
 306         */
 307        if (info->flash_id != FLASH_UNKNOWN) {
 308                addr = (volatile unsigned long *)info->start[0];
 309
 310                *addr = 0xF0F0F0F0;     /* reset bank */
 311        }
 312
 313        return (info->size);
 314}
 315
 316
 317/*-----------------------------------------------------------------------
 318 */
 319
 320int     flash_erase (flash_info_t *info, int s_first, int s_last)
 321{
 322        vu_long *addr = (vu_long*)(info->start[0]);
 323        int flag, prot, sect, l_sect;
 324        ulong start, now, last;
 325
 326        if ((s_first < 0) || (s_first > s_last)) {
 327                if (info->flash_id == FLASH_UNKNOWN) {
 328                        printf ("- missing\n");
 329                } else {
 330                        printf ("- no sectors to erase\n");
 331                }
 332                return 1;
 333        }
 334
 335        if ((info->flash_id == FLASH_UNKNOWN) ||
 336            (info->flash_id > FLASH_AMD_COMP)) {
 337                printf ("Can't erase unknown flash type %08lx - aborted\n",
 338                        info->flash_id);
 339                return 1;
 340        }
 341
 342        prot = 0;
 343        for (sect=s_first; sect<=s_last; ++sect) {
 344                if (info->protect[sect]) {
 345                        prot++;
 346                }
 347        }
 348
 349        if (prot) {
 350                printf ("- Warning: %d protected sectors will not be erased!\n",
 351                        prot);
 352        } else {
 353                printf ("\n");
 354        }
 355
 356        l_sect = -1;
 357
 358        /* Disable interrupts which might cause a timeout here */
 359        flag = disable_interrupts();
 360
 361        addr[0xAAA] = 0xAAAAAAAA;
 362        addr[0x555] = 0x55555555;
 363        addr[0xAAA] = 0x80808080;
 364        addr[0xAAA] = 0xAAAAAAAA;
 365        addr[0x555] = 0x55555555;
 366
 367        /* Start erase on unprotected sectors */
 368        for (sect = s_first; sect<=s_last; sect++) {
 369                if (info->protect[sect] == 0) { /* not protected */
 370                        addr = (vu_long *)(info->start[sect]) ;
 371                        addr[0] = 0x30303030 ;
 372                        l_sect = sect;
 373                }
 374        }
 375
 376        /* re-enable interrupts if necessary */
 377        if (flag)
 378                enable_interrupts();
 379
 380        /* wait at least 80us - let's wait 1 ms */
 381        udelay (1000);
 382
 383        /*
 384         * We wait for the last triggered sector
 385         */
 386        if (l_sect < 0)
 387                goto DONE;
 388
 389        start = get_timer (0);
 390        last  = start;
 391        addr = (vu_long *)(info->start[l_sect]);
 392        while ((addr[0] & 0x80808080) != 0x80808080) {
 393                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 394                        printf ("Timeout\n");
 395                        return 1;
 396                }
 397                /* show that we're waiting */
 398                if ((now - last) > 1000) {      /* every second */
 399                        putc ('.');
 400                        last = now;
 401                }
 402        }
 403
 404DONE:
 405        /* reset to read mode */
 406        addr = (vu_long *)info->start[0];
 407        addr[0] = 0xF0F0F0F0;   /* reset bank */
 408
 409        printf (" done\n");
 410        return 0;
 411}
 412
 413/*-----------------------------------------------------------------------
 414 * Copy memory to flash, returns:
 415 * 0 - OK
 416 * 1 - write timeout
 417 * 2 - Flash not erased
 418 */
 419
 420int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 421{
 422        ulong cp, wp, data;
 423        int i, l, rc;
 424
 425        wp = (addr & ~3);       /* get lower word aligned address */
 426
 427        /*
 428         * handle unaligned start bytes
 429         */
 430        if ((l = addr - wp) != 0) {
 431                data = 0;
 432                for (i=0, cp=wp; i<l; ++i, ++cp) {
 433                        data = (data << 8) | (*(uchar *)cp);
 434                }
 435                for (; i<4 && cnt>0; ++i) {
 436                        data = (data << 8) | *src++;
 437                        --cnt;
 438                        ++cp;
 439                }
 440                for (; cnt==0 && i<4; ++i, ++cp) {
 441                        data = (data << 8) | (*(uchar *)cp);
 442                }
 443
 444                if ((rc = write_word(info, wp, data)) != 0) {
 445                        return (rc);
 446                }
 447                wp += 4;
 448        }
 449
 450        /*
 451         * handle word aligned part
 452         */
 453        while (cnt >= 4) {
 454                data = 0;
 455                for (i=0; i<4; ++i) {
 456                        data = (data << 8) | *src++;
 457                }
 458                if ((rc = write_word(info, wp, data)) != 0) {
 459                        return (rc);
 460                }
 461                wp  += 4;
 462                cnt -= 4;
 463        }
 464
 465        if (cnt == 0) {
 466                return (0);
 467        }
 468
 469        /*
 470         * handle unaligned tail bytes
 471         */
 472        data = 0;
 473        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 474                data = (data << 8) | *src++;
 475                --cnt;
 476        }
 477        for (; i<4; ++i, ++cp) {
 478                data = (data << 8) | (*(uchar *)cp);
 479        }
 480
 481        return (write_word(info, wp, data));
 482}
 483
 484/*-----------------------------------------------------------------------
 485 * Write a word to Flash, returns:
 486 * 0 - OK
 487 * 1 - write timeout
 488 * 2 - Flash not erased
 489 */
 490static int write_word (flash_info_t *info, ulong dest, ulong data)
 491{
 492        vu_long *addr = (vu_long *)(info->start[0]);
 493        ulong start;
 494        int flag;
 495
 496        /* Check if Flash is (sufficiently) erased */
 497        if ((*((vu_long *)dest) & data) != data) {
 498                return (2);
 499        }
 500        /* Disable interrupts which might cause a timeout here */
 501        flag = disable_interrupts();
 502
 503        addr[0xAAA] = 0xAAAAAAAA;
 504        addr[0x555] = 0x55555555;
 505        addr[0xAAA] = 0xA0A0A0A0;
 506
 507        *((vu_long *)dest) = data;
 508
 509        /* re-enable interrupts if necessary */
 510        if (flag)
 511                enable_interrupts();
 512
 513        /* data polling for D7 */
 514        start = get_timer (0);
 515        while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
 516                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 517                        return (1);
 518                }
 519        }
 520        return (0);
 521}
 522
 523/*-----------------------------------------------------------------------
 524 */
 525