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