uboot/board/RPXClassic/flash.c
<<
>>
Prefs
   1/*
   2 * (C)  Copyright 2001
   3 * Stäubli Faverges - <www.staubli.com>
   4 * Pierre AUBERT  p.aubert@staubli.com
   5 * U-Boot port on RPXClassic LF (CLLF_BW31) board
   6 *
   7 * RPXClassic uses Am29DL323B flash memory with 2 banks
   8 *
   9 *
  10 * (C) Copyright 2000
  11 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  12 *
  13 * See file CREDITS for list of people who contributed to this
  14 * project.
  15 *
  16 * This program is free software; you can redistribute it and/or
  17 * modify it under the terms of the GNU General Public License as
  18 * published by the Free Software Foundation; either version 2 of
  19 * the License, or (at your option) any later version.
  20 *
  21 * This program is distributed in the hope that it will be useful,
  22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24 * GNU General Public License for more details.
  25 *
  26 * You should have received a copy of the GNU General Public License
  27 * along with this program; if not, write to the Free Software
  28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  29 * MA 02111-1307 USA
  30 */
  31
  32
  33#include <common.h>
  34#include <mpc8xx.h>
  35
  36flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
  37
  38/*-----------------------------------------------------------------------
  39 * Functions
  40 */
  41static ulong flash_get_size (vu_long *addr, flash_info_t *info);
  42static int write_word (flash_info_t *info, ulong dest, ulong data);
  43static void flash_get_offsets (ulong base, flash_info_t *info);
  44
  45/*-----------------------------------------------------------------------
  46 */
  47
  48unsigned long flash_init (void)
  49{
  50        unsigned long size_b0 ;
  51        int i;
  52
  53        /* Init: no FLASHes known */
  54        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  55                flash_info[i].flash_id = FLASH_UNKNOWN;
  56        }
  57
  58        size_b0 = flash_get_size((vu_long *)CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  59
  60
  61        flash_get_offsets (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
  62
  63#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
  64        /* monitor protection ON by default */
  65        flash_protect(FLAG_PROTECT_SET,
  66                      CONFIG_SYS_MONITOR_BASE,
  67                      CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
  68                      &flash_info[0]);
  69#endif
  70
  71        flash_info[0].size = size_b0;
  72
  73        return (size_b0);
  74}
  75
  76/*-----------------------------------------------------------------------
  77 */
  78static void flash_get_offsets (ulong base, flash_info_t *info)
  79{
  80        int i;
  81
  82        if (info->flash_id & FLASH_BTYPE) {
  83                /* set sector offsets for bottom boot block type        */
  84                info->start[0] = base + 0x00000000;
  85                info->start[1] = base + 0x00008000;
  86                info->start[2] = base + 0x00010000;
  87                info->start[3] = base + 0x00018000;
  88                info->start[4] = base + 0x00020000;
  89                info->start[5] = base + 0x00028000;
  90                info->start[6] = base + 0x00030000;
  91                info->start[7] = base + 0x00038000;
  92                for (i = 8; i < info->sector_count; i++) {
  93                        info->start[i] = base + ((i-7) * 0x00040000) ;
  94                }
  95        }
  96}
  97
  98/*-----------------------------------------------------------------------
  99 */
 100void flash_print_info  (flash_info_t *info)
 101{
 102        int i;
 103
 104        if (info->flash_id == FLASH_UNKNOWN) {
 105                printf ("missing or unknown FLASH type\n");
 106                return;
 107        }
 108
 109        switch (info->flash_id & FLASH_VENDMASK) {
 110        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 111        default:                printf ("Unknown Vendor ");     break;
 112        }
 113
 114        switch (info->flash_id & FLASH_TYPEMASK) {
 115        case FLASH_AMDL323B:
 116            printf ("AMDL323DB (16 Mbytes, bottom boot sect)\n");
 117            break;
 118        default:
 119            printf ("Unknown Chip Type\n");
 120            break;
 121        }
 122
 123        printf ("  Size: %ld MB in %d Sectors\n",
 124                info->size >> 20, info->sector_count);
 125
 126        printf ("  Sector Start Addresses:");
 127        for (i=0; i<info->sector_count; ++i) {
 128                if ((i % 5) == 0)
 129                        printf ("\n   ");
 130                printf (" %08lX%s",
 131                        info->start[i],
 132                        info->protect[i] ? " (RO)" : "     "
 133                );
 134        }
 135        printf ("\n");
 136}
 137
 138/*-----------------------------------------------------------------------
 139 */
 140
 141
 142/*-----------------------------------------------------------------------
 143 */
 144
 145/*
 146 * The following code cannot be run from FLASH!
 147 */
 148
 149static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 150{
 151        short i;
 152        ulong value;
 153        ulong base = (ulong)addr;
 154
 155        /* Reset flash componeny                                             */
 156        addr [0] = 0xf0f0f0f0;
 157
 158        /* Write auto select command: read Manufacturer ID */
 159        addr[0xAAA] = 0xAAAAAAAA ;
 160        addr[0x555] = 0x55555555 ;
 161        addr[0xAAA] = 0x90909090 ;
 162
 163        value = addr[0] ;
 164
 165        switch (value & 0x00FF00FF) {
 166        case AMD_MANUFACT:
 167                info->flash_id = FLASH_MAN_AMD;
 168                break;
 169        default:
 170                info->flash_id = FLASH_UNKNOWN;
 171                info->sector_count = 0;
 172                info->size = 0;
 173                return (0);                     /* no or unknown flash  */
 174        }
 175
 176        value = addr[2] ;               /* device ID            */
 177
 178        switch (value & 0x00FF00FF) {
 179        case (AMD_ID_DL323B & 0x00FF00FF):
 180            info->flash_id += FLASH_AMDL323B;
 181            info->sector_count = 71;
 182            info->size = 0x01000000;            /* 16 Mb                     */
 183
 184            break;
 185        default:
 186                info->flash_id = FLASH_UNKNOWN;
 187                return (0);                     /* => no or unknown flash */
 188
 189        }
 190        /* set up sector start address table */
 191        /* set sector offsets for bottom boot block type        */
 192        info->start[0] = base + 0x00000000;
 193        info->start[1] = base + 0x00008000;
 194        info->start[2] = base + 0x00010000;
 195        info->start[3] = base + 0x00018000;
 196        info->start[4] = base + 0x00020000;
 197        info->start[5] = base + 0x00028000;
 198        info->start[6] = base + 0x00030000;
 199        info->start[7] = base + 0x00038000;
 200        for (i = 8; i < info->sector_count; i++) {
 201            info->start[i] = base + ((i-7) * 0x00040000) ;
 202        }
 203
 204        /* check for protected sectors */
 205        for (i = 0; i < 23; i++) {
 206            /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 207            /* D0 = 1 if protected */
 208            addr = (volatile unsigned long *)(info->start[i]);
 209            info->protect[i] = addr[4] & 1 ;
 210        }
 211        /* Check for protected sectors in the 2nd bank                       */
 212        addr[0x100AAA] = 0xAAAAAAAA ;
 213        addr[0x100555] = 0x55555555 ;
 214        addr[0x100AAA] = 0x90909090 ;
 215
 216        for (i = 23; i < info->sector_count; i++) {
 217            /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 218            /* D0 = 1 if protected */
 219            addr = (volatile unsigned long *)(info->start[i]);
 220            info->protect[i] = addr[4] & 1 ;
 221        }
 222
 223        /*
 224         * Prevent writes to uninitialized FLASH.
 225         */
 226        if (info->flash_id != FLASH_UNKNOWN) {
 227                addr = (volatile unsigned long *)info->start[0];
 228
 229                *addr = 0xF0F0F0F0;     /* reset bank 1                      */
 230                addr = (volatile unsigned long *)info->start[23];
 231
 232                *addr = 0xF0F0F0F0;     /* reset bank 2                      */
 233
 234        }
 235
 236        return (info->size);
 237}
 238
 239
 240/*-----------------------------------------------------------------------
 241 */
 242
 243int     flash_erase (flash_info_t *info, int s_first, int s_last)
 244{
 245        vu_long *addr = (vu_long*)(info->start[0]);
 246        int flag, prot, sect, l_sect;
 247        ulong start, now, last;
 248
 249        if ((s_first < 0) || (s_first > s_last)) {
 250                if (info->flash_id == FLASH_UNKNOWN) {
 251                        printf ("- missing\n");
 252                } else {
 253                        printf ("- no sectors to erase\n");
 254                }
 255                return 1;
 256        }
 257
 258        if ((info->flash_id == FLASH_UNKNOWN) ||
 259            (info->flash_id > FLASH_AMD_COMP)) {
 260                printf ("Can't erase unknown flash type %08lx - aborted\n",
 261                        info->flash_id);
 262                return 1;
 263        }
 264
 265        prot = 0;
 266        for (sect=s_first; sect<=s_last; ++sect) {
 267                if (info->protect[sect]) {
 268                        prot++;
 269                }
 270        }
 271
 272        if (prot) {
 273                printf ("- Warning: %d protected sectors will not be erased!\n",
 274                        prot);
 275        } else {
 276                printf ("\n");
 277        }
 278
 279        l_sect = -1;
 280
 281        /* Disable interrupts which might cause a timeout here */
 282        flag = disable_interrupts();
 283
 284        addr[0xAAA] = 0xAAAAAAAA;
 285        addr[0x555] = 0x55555555;
 286        addr[0xAAA] = 0x80808080;
 287        addr[0xAAA] = 0xAAAAAAAA;
 288        addr[0x555] = 0x55555555;
 289
 290        /* Start erase on unprotected sectors */
 291        for (sect = s_first; sect<=s_last; sect++) {
 292                if (info->protect[sect] == 0) { /* not protected */
 293                        addr = (vu_long *)(info->start[sect]) ;
 294                        addr[0] = 0x30303030 ;
 295                        l_sect = sect;
 296                }
 297        }
 298
 299        /* re-enable interrupts if necessary */
 300        if (flag)
 301                enable_interrupts();
 302
 303        /* wait at least 80us - let's wait 1 ms */
 304        udelay (1000);
 305
 306        /*
 307         * We wait for the last triggered sector
 308         */
 309        if (l_sect < 0)
 310                goto DONE;
 311
 312        start = get_timer (0);
 313        last  = start;
 314        addr = (vu_long *)(info->start[l_sect]);
 315        while ((addr[0] & 0x80808080) != 0x80808080) {
 316                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 317                        printf ("Timeout\n");
 318                        return 1;
 319                }
 320                /* show that we're waiting */
 321                if ((now - last) > 1000) {      /* every second */
 322                        putc ('.');
 323                        last = now;
 324                }
 325        }
 326
 327DONE:
 328        /* reset to read mode */
 329        addr = (vu_long *)info->start[0];
 330        addr[0] = 0xF0F0F0F0;   /* reset bank */
 331
 332        printf (" done\n");
 333        return 0;
 334}
 335
 336/*-----------------------------------------------------------------------
 337 * Copy memory to flash, returns:
 338 * 0 - OK
 339 * 1 - write timeout
 340 * 2 - Flash not erased
 341 */
 342
 343int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 344{
 345        ulong cp, wp, data;
 346        int i, l, rc;
 347
 348        wp = (addr & ~3);       /* get lower word aligned address */
 349
 350        /*
 351         * handle unaligned start bytes
 352         */
 353        if ((l = addr - wp) != 0) {
 354                data = 0;
 355                for (i=0, cp=wp; i<l; ++i, ++cp) {
 356                        data = (data << 8) | (*(uchar *)cp);
 357                }
 358                for (; i<4 && cnt>0; ++i) {
 359                        data = (data << 8) | *src++;
 360                        --cnt;
 361                        ++cp;
 362                }
 363                for (; cnt==0 && i<4; ++i, ++cp) {
 364                        data = (data << 8) | (*(uchar *)cp);
 365                }
 366
 367                if ((rc = write_word(info, wp, data)) != 0) {
 368                        return (rc);
 369                }
 370                wp += 4;
 371        }
 372
 373        /*
 374         * handle word aligned part
 375         */
 376        while (cnt >= 4) {
 377                data = 0;
 378                for (i=0; i<4; ++i) {
 379                        data = (data << 8) | *src++;
 380                }
 381                if ((rc = write_word(info, wp, data)) != 0) {
 382                        return (rc);
 383                }
 384                wp  += 4;
 385                cnt -= 4;
 386        }
 387
 388        if (cnt == 0) {
 389                return (0);
 390        }
 391
 392        /*
 393         * handle unaligned tail bytes
 394         */
 395        data = 0;
 396        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 397                data = (data << 8) | *src++;
 398                --cnt;
 399        }
 400        for (; i<4; ++i, ++cp) {
 401                data = (data << 8) | (*(uchar *)cp);
 402        }
 403
 404        return (write_word(info, wp, data));
 405}
 406
 407/*-----------------------------------------------------------------------
 408 * Write a word to Flash, returns:
 409 * 0 - OK
 410 * 1 - write timeout
 411 * 2 - Flash not erased
 412 */
 413static int write_word (flash_info_t *info, ulong dest, ulong data)
 414{
 415        vu_long *addr = (vu_long *)(info->start[0]);
 416        ulong start;
 417        int flag;
 418
 419        /* Check if Flash is (sufficiently) erased */
 420        if ((*((vu_long *)dest) & data) != data) {
 421                return (2);
 422        }
 423        /* Disable interrupts which might cause a timeout here */
 424        flag = disable_interrupts();
 425
 426        addr[0xAAA] = 0xAAAAAAAA;
 427        addr[0x555] = 0x55555555;
 428        addr[0xAAA] = 0xA0A0A0A0;
 429
 430        *((vu_long *)dest) = data;
 431
 432        /* re-enable interrupts if necessary */
 433        if (flag)
 434                enable_interrupts();
 435
 436        /* data polling for D7 */
 437        start = get_timer (0);
 438        while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) {
 439                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 440                        return (1);
 441                }
 442        }
 443        return (0);
 444}
 445
 446/*-----------------------------------------------------------------------
 447 */
 448