uboot/board/RPXlite_dw/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2004
   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/* Yes,Yoo.They do use other FLASH for the board.
  39 *
  40 * Sam Song, IEMC. SHU, samsongshu@yahoo.com.cn
  41 * U-Boot port on RPXlite DW version board
  42 *
  43 * By now,it uses 4 AM29DL323DB90VI devices(4x8bit).
  44 * The total FLASH has 16MB(4x4MB).
  45 * I just made some necessary changes on the basis of Wolfgang and Yoo's job.
  46 *
  47 * June 8, 2004 */
  48
  49#include <common.h>
  50#include <mpc8xx.h>
  51
  52flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  53
  54/*-----------------------------------------------------------------------
  55 * Functions   vu_long : volatile unsigned long IN include/common.h
  56 */
  57static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  58static int write_word (flash_info_t *info, ulong dest, ulong data);
  59static void flash_get_offsets (ulong base, flash_info_t *info);
  60
  61unsigned long flash_init (void)
  62{
  63        unsigned long size_b0 ;
  64        int i;
  65
  66        /* Init: no FLASHes known */
  67        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  68                flash_info[i].flash_id = FLASH_UNKNOWN;
  69        }
  70
  71        size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  72        flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  73
  74#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  75        /* If Monitor is in the cope of FLASH,then
  76         * protect this area by default in case for
  77         * other occupation. [SAM] */
  78
  79        /* monitor protection ON by default */
  80        flash_protect(FLAG_PROTECT_SET,
  81                      CONFIG_SYS_MONITOR_BASE,
  82                      CONFIG_SYS_MONITOR_BASE+CONFIG_SYS_MONITOR_LEN-1,
  83                      &flash_info[0]);
  84#endif
  85        flash_info[0].size = size_b0;
  86        return (size_b0);
  87}
  88
  89static void flash_get_offsets (ulong base, flash_info_t *info)
  90{
  91        int i;
  92
  93        /* set up sector start address table */
  94        if (info->flash_id & FLASH_BTYPE) {
  95                info->start[0] = base + 0x00000000;
  96                info->start[1] = base + 0x00008000;
  97                info->start[2] = base + 0x00010000;
  98                info->start[3] = base + 0x00018000;
  99                info->start[4] = base + 0x00020000;
 100                info->start[5] = base + 0x00028000;
 101                info->start[6] = base + 0x00030000;
 102                info->start[7] = base + 0x00038000;
 103
 104                for (i = 8; i < info->sector_count; i++) {
 105                        info->start[i] = base + ((i-7) * 0x00040000);
 106                }
 107        } else {
 108                i = info->sector_count - 1;
 109                info->start[i--] = base + info->size - 0x00010000;
 110                info->start[i--] = base + info->size - 0x00018000;
 111                info->start[i--] = base + info->size - 0x00020000;
 112                for (; i >= 0; i--) {
 113                        info->start[i] = base + i * 0x00040000;
 114                }
 115        }
 116
 117}
 118
 119void flash_print_info  (flash_info_t *info)
 120{
 121        int i;
 122
 123        if (info->flash_id == FLASH_UNKNOWN) {
 124                printf ("missing or unknown FLASH type\n");
 125                return;
 126        }
 127
 128        switch (info->flash_id & FLASH_VENDMASK) {
 129        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 130        case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
 131        default:                printf ("Unknown Vendor ");     break;
 132        }
 133
 134        switch (info->flash_id & FLASH_TYPEMASK) {
 135        case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
 136                                break;
 137        case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
 138                                break;
 139        case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
 140                                break;
 141        case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
 142                                break;
 143        case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
 144                                break;
 145        case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
 146                                break;
 147        case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
 148                                break;
 149        case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
 150                                break;
 151        case FLASH_AMDL323B:    printf ("AM29DL323B (32 Mbit, bottom boot sector)\n");
 152                                break;
 153        /* I just add the FLASH_AMDL323B for RPXlite_DW BOARD. [SAM]  */
 154        default:                printf ("Unknown Chip Type\n");
 155                                break;
 156        }
 157        printf ("  Size: %ld MB in %d Sectors\n",info->size >> 20, info->sector_count);
 158        printf ("  Sector Start Addresses:");
 159        for (i=0; i<info->sector_count; ++i) {
 160                if ((i % 5) == 0)
 161                        printf ("\n   ");
 162                printf (" %08lX%s",info->start[i],info->protect[i] ? " (RO)" : "     ");
 163        }
 164        printf ("\n");
 165        return;
 166}
 167
 168static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 169{
 170        short i;
 171        ulong value;
 172        ulong base = (ulong)addr;
 173
 174        /* Write auto select command: read Manufacturer ID */
 175        addr[0xAAA] = 0x00AA00AA ;
 176        addr[0x555] = 0x00550055 ;
 177        addr[0xAAA] = 0x00900090 ;
 178
 179        value = addr[0] ;
 180        switch (value & 0x00FF00FF) {
 181        case AMD_MANUFACT:                      /* AMD_MANUFACT =0x00010001 in flash.h */
 182                info->flash_id = FLASH_MAN_AMD; /* FLASH_MAN_AMD=0x00000000 in flash.h */
 183                break;
 184        case FUJ_MANUFACT:
 185                info->flash_id = FLASH_MAN_FUJ;
 186                break;
 187        default:
 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[2] ;                       /* device ID            */
 195        switch (value & 0x00FF00FF) {
 196        case (AMD_ID_LV400T & 0x00FF00FF):
 197                info->flash_id += FLASH_AM400T;
 198                info->sector_count = 11;
 199                info->size = 0x00100000;
 200                break;                          /* => 1 MB              */
 201        case (AMD_ID_LV400B & 0x00FF00FF):
 202                info->flash_id += FLASH_AM400B;
 203                info->sector_count = 11;
 204                info->size = 0x00100000;
 205                break;                          /* => 1 MB              */
 206        case (AMD_ID_LV800T & 0x00FF00FF):
 207                info->flash_id += FLASH_AM800T;
 208                info->sector_count = 19;
 209                info->size = 0x00200000;
 210                break;                          /* => 2 MB              */
 211        case (AMD_ID_LV800B & 0x00FF00FF):
 212                info->flash_id += FLASH_AM800B;
 213                info->sector_count = 19;
 214                info->size = 0x00400000;        /* Size doubled by yooth */
 215                break;                          /* => 4 MB               */
 216        case (AMD_ID_LV160T & 0x00FF00FF):
 217                info->flash_id += FLASH_AM160T;
 218                info->sector_count = 35;
 219                info->size = 0x00400000;
 220                break;                          /* => 4 MB              */
 221        case (AMD_ID_LV160B & 0x00FF00FF):
 222                info->flash_id += FLASH_AM160B;
 223                info->sector_count = 35;
 224                info->size = 0x00400000;
 225                break;                          /* => 4 MB              */
 226        case (AMD_ID_DL323B & 0x00FF00FF):
 227                info->flash_id += FLASH_AMDL323B;
 228                info->sector_count = 71;
 229                info->size = 0x01000000;
 230                break;                          /* => 16 MB(4x4MB)  */
 231        /* AMD_ID_DL323B= 0x22532253  FLASH_AMDL323B= 0x0013
 232         * AMD_ID_DL323B could be found in <flash.h>.[SAM]
 233         * So we could get : flash_id = 0x00000013.
 234         * The first four-bit represents VEDOR ID,leaving others for FLASH ID. */
 235        default:
 236                info->flash_id = FLASH_UNKNOWN;
 237                return (0);                     /* => no or unknown flash */
 238
 239        }
 240        /* set up sector start address table */
 241        if (info->flash_id & FLASH_BTYPE) {
 242        /* FLASH_BTYPE=0x0001 mask for bottom boot sector type.If the last bit equals 1,
 243         * it means bottom boot flash. GOOD IDEA! [SAM]
 244         */
 245
 246        /* set sector offsets for bottom boot block type        */
 247                info->start[0] = base + 0x00000000;
 248                info->start[1] = base + 0x00008000;
 249                info->start[2] = base + 0x00010000;
 250                info->start[3] = base + 0x00018000;
 251                info->start[4] = base + 0x00020000;
 252                info->start[5] = base + 0x00028000;
 253                info->start[6] = base + 0x00030000;
 254                info->start[7] = base + 0x00038000;
 255
 256                for (i = 8; i < info->sector_count; i++) {
 257                        info->start[i] = base + ((i-7) * 0x00040000) ;
 258                }
 259        } else {
 260                /* set sector offsets for top boot block type           */
 261                i = info->sector_count - 1;
 262                info->start[i--] = base + info->size - 0x00010000;
 263                info->start[i--] = base + info->size - 0x00018000;
 264                info->start[i--] = base + info->size - 0x00020000;
 265                for (; i >= 0; i--) {
 266                        info->start[i] = base + i * 0x00040000;
 267                }
 268        }
 269
 270        /* check for protected sectors */
 271        for (i = 0; i < info->sector_count; i++) {
 272                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 273                /* D0 = 1 if protected */
 274                addr = (volatile unsigned long *)(info->start[i]);
 275                /* info->protect[i] = addr[4] & 1 ; */
 276                /* Mask it for disorder FLASH protection **[Sam]** */
 277        }
 278
 279        /*
 280         * Prevent writes to uninitialized FLASH.
 281         */
 282        if (info->flash_id != FLASH_UNKNOWN) {
 283                addr = (volatile unsigned long *)info->start[0];
 284
 285                *addr = 0xF0F0F0F0;     /* reset bank */
 286        }
 287        return (info->size);
 288}
 289
 290int     flash_erase (flash_info_t *info, int s_first, int s_last)
 291{
 292        vu_long *addr = (vu_long*)(info->start[0]);
 293        int flag, prot, sect, l_sect;
 294        ulong start, now, last;
 295
 296        if ((s_first < 0) || (s_first > s_last)) {
 297                if (info->flash_id == FLASH_UNKNOWN) {
 298                        printf ("- missing\n");
 299                } else {
 300                        printf ("- no sectors to erase\n");
 301                }
 302                return 1;
 303        }
 304
 305        if ((info->flash_id == FLASH_UNKNOWN) ||
 306            (info->flash_id > FLASH_AMD_COMP)) {
 307                printf ("Can't erase unknown flash type %08lx - aborted\n",
 308                        info->flash_id);
 309                return 1;
 310        }
 311
 312        prot = 0;
 313        for (sect=s_first; sect<=s_last; ++sect) {
 314                if (info->protect[sect]) {
 315                        prot++;
 316                }
 317        }
 318
 319        if (prot) {
 320                printf ("- Warning: %d protected sectors will not be erased!\n",
 321                        prot);
 322        } else {
 323                printf ("\n");
 324        }
 325
 326        l_sect = -1;
 327
 328        /* Disable interrupts which might cause a timeout here */
 329        flag = disable_interrupts();
 330
 331        addr[0xAAA] = 0xAAAAAAAA;
 332        addr[0x555] = 0x55555555;
 333        addr[0xAAA] = 0x80808080;
 334        addr[0xAAA] = 0xAAAAAAAA;
 335        addr[0x555] = 0x55555555;
 336
 337        /* Start erase on unprotected sectors */
 338        for (sect = s_first; sect<=s_last; sect++) {
 339                if (info->protect[sect] == 0) { /* not protected */
 340                        addr = (vu_long *)(info->start[sect]) ;
 341                        addr[0] = 0x30303030 ;
 342                        l_sect = sect;
 343                }
 344        }
 345
 346        /* re-enable interrupts if necessary */
 347        if (flag)
 348                enable_interrupts();
 349
 350        /* wait at least 80us - let's wait 1 ms */
 351        udelay (1000);
 352
 353        /*
 354         * We wait for the last triggered sector
 355         */
 356        if (l_sect < 0)
 357                goto DONE;
 358
 359        start = get_timer (0);
 360        last  = start;
 361        addr = (vu_long *)(info->start[l_sect]);
 362        while ((addr[0] & 0x80808080) != 0x80808080) {
 363                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 364                        printf ("Timeout\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_long *)info->start[0];
 377        addr[0] = 0xF0F0F0F0;   /* reset bank */
 378
 379        printf (" done\n");
 380        return 0;
 381}
 382
 383/*-----------------------------------------------------------------------
 384 * Copy memory to flash, returns:
 385 * 0 - OK
 386 * 1 - write timeout
 387 * 2 - Flash not erased
 388 */
 389
 390int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 391{
 392        ulong cp, wp, data;
 393        int i, l, rc;
 394
 395        wp = (addr & ~3);       /* get lower word aligned address */
 396
 397        /*
 398         * handle unaligned start bytes
 399         */
 400        if ((l = addr - wp) != 0) {
 401                data = 0;
 402                for (i=0, cp=wp; i<l; ++i, ++cp) {
 403                        data = (data << 8) | (*(uchar *)cp);
 404                }
 405                for (; i<4 && cnt>0; ++i) {
 406                        data = (data << 8) | *src++;
 407                        --cnt;
 408                        ++cp;
 409                }
 410                for (; cnt==0 && i<4; ++i, ++cp) {
 411                        data = (data << 8) | (*(uchar *)cp);
 412                }
 413
 414                if ((rc = write_word(info, wp, data)) != 0) {
 415                        return (rc);
 416                }
 417                wp += 4;
 418        }
 419
 420        /*
 421         * handle word aligned part
 422         */
 423        while (cnt >= 4) {
 424                data = 0;
 425                for (i=0; i<4; ++i) {
 426                        data = (data << 8) | *src++;
 427                }
 428                if ((rc = write_word(info, wp, data)) != 0) {
 429                        return (rc);
 430                }
 431                wp  += 4;
 432                cnt -= 4;
 433        }
 434
 435        if (cnt == 0) {
 436                return (0);
 437        }
 438
 439        /*
 440         * handle unaligned tail bytes
 441         */
 442        data = 0;
 443        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 444                data = (data << 8) | *src++;
 445                --cnt;
 446        }
 447        for (; i<4; ++i, ++cp) {
 448                data = (data << 8) | (*(uchar *)cp);
 449        }
 450        return (write_word(info, wp, data));
 451}
 452
 453/*-----------------------------------------------------------------------
 454 * Write a word to Flash, returns:
 455 * 0 - OK
 456 * 1 - write timeout
 457 * 2 - Flash not erased
 458 */
 459static int write_word (flash_info_t *info, ulong dest, ulong data)
 460{
 461        vu_long *addr = (vu_long *)(info->start[0]);
 462        ulong start;
 463        int flag;
 464
 465        /* Check if Flash is (sufficiently) erased */
 466        if ((*((vu_long *)dest) & data) != data) {
 467                return (2);
 468        }
 469        /* Disable interrupts which might cause a timeout here */
 470        flag = disable_interrupts();
 471
 472        addr[0xAAA] = 0xAAAAAAAA;
 473        addr[0x555] = 0x55555555;
 474        addr[0xAAA] = 0xA0A0A0A0;
 475
 476        *((vu_long *)dest) = data;
 477
 478        /* re-enable interrupts if necessary */
 479        if (flag)
 480                enable_interrupts();
 481
 482        /* data polling for D7 */
 483        start = get_timer (0);
 484        while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
 485                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 486                        return (1);
 487                }
 488        }
 489        return (0);
 490}
 491