uboot/board/impa7/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   4 * Marius Groeger <mgroeger@sysgo.de>
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 */
  24
  25#include <common.h>
  26
  27#define FLASH_BANK_SIZE 0x800000
  28#define MAIN_SECT_SIZE  0x20000
  29#define PARAM_SECT_SIZE 0x4000
  30
  31flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  32
  33
  34/*-----------------------------------------------------------------------
  35 */
  36
  37ulong flash_init (void)
  38{
  39        int i, j;
  40        ulong size = 0;
  41
  42        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  43                ulong flashbase = 0;
  44
  45                flash_info[i].flash_id =
  46                        (INTEL_MANUFACT & FLASH_VENDMASK) |
  47                        (INTEL_ID_28F320B3T & FLASH_TYPEMASK);
  48                flash_info[i].size = FLASH_BANK_SIZE;
  49                flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
  50                memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
  51                if (i == 0)
  52                        flashbase = PHYS_FLASH_1;
  53                else if (i == 1)
  54                        flashbase = PHYS_FLASH_2;
  55                else
  56                        panic ("configured too many flash banks!\n");
  57                for (j = 0; j < flash_info[i].sector_count; j++) {
  58                        if (j <= 7) {
  59                                flash_info[i].start[j] =
  60                                        flashbase + j * PARAM_SECT_SIZE;
  61                        } else {
  62                                flash_info[i].start[j] =
  63                                        flashbase + (j - 7) * MAIN_SECT_SIZE;
  64                        }
  65                }
  66                size += flash_info[i].size;
  67        }
  68
  69        /* Protect monitor and environment sectors
  70         */
  71        flash_protect (FLAG_PROTECT_SET,
  72                       CONFIG_SYS_FLASH_BASE,
  73                       CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
  74                       &flash_info[0]);
  75
  76        flash_protect (FLAG_PROTECT_SET,
  77                       CONFIG_ENV_ADDR,
  78                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
  79
  80        return size;
  81}
  82
  83/*-----------------------------------------------------------------------
  84 */
  85void flash_print_info (flash_info_t * info)
  86{
  87        int i;
  88
  89        switch (info->flash_id & FLASH_VENDMASK) {
  90        case (INTEL_MANUFACT & FLASH_VENDMASK):
  91                printf ("Intel: ");
  92                break;
  93        default:
  94                printf ("Unknown Vendor ");
  95                break;
  96        }
  97
  98        switch (info->flash_id & FLASH_TYPEMASK) {
  99        case (INTEL_ID_28F320B3T & FLASH_TYPEMASK):
 100                printf ("28F320F3B (16Mbit)\n");
 101                break;
 102        default:
 103                printf ("Unknown Chip Type\n");
 104                goto Done;
 105                break;
 106        }
 107
 108        printf ("  Size: %ld MB in %d Sectors\n",
 109                info->size >> 20, info->sector_count);
 110
 111        printf ("  Sector Start Addresses:");
 112        for (i = 0; i < info->sector_count; i++) {
 113                if ((i % 5) == 0) {
 114                        printf ("\n   ");
 115                }
 116                printf (" %08lX%s", info->start[i],
 117                        info->protect[i] ? " (RO)" : "     ");
 118        }
 119        printf ("\n");
 120
 121      Done:;
 122}
 123
 124/*-----------------------------------------------------------------------
 125 */
 126
 127int flash_erase (flash_info_t * info, int s_first, int s_last)
 128{
 129        int flag, prot, sect;
 130        int rc = ERR_OK;
 131
 132        if (info->flash_id == FLASH_UNKNOWN)
 133                return ERR_UNKNOWN_FLASH_TYPE;
 134
 135        if ((s_first < 0) || (s_first > s_last)) {
 136                return ERR_INVAL;
 137        }
 138
 139        if ((info->flash_id & FLASH_VENDMASK) !=
 140            (INTEL_MANUFACT & FLASH_VENDMASK)) {
 141                return ERR_UNKNOWN_FLASH_VENDOR;
 142        }
 143
 144        prot = 0;
 145        for (sect = s_first; sect <= s_last; ++sect) {
 146                if (info->protect[sect]) {
 147                        prot++;
 148                }
 149        }
 150        if (prot)
 151                return ERR_PROTECTED;
 152
 153        /*
 154         * Disable interrupts which might cause a timeout
 155         * here. Remember that our exception vectors are
 156         * at address 0 in the flash, and we don't want a
 157         * (ticker) exception to happen while the flash
 158         * chip is in programming mode.
 159         */
 160        flag = disable_interrupts ();
 161
 162        /* Start erase on unprotected sectors */
 163        for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
 164
 165                printf ("Erasing sector %2d ... ", sect);
 166
 167                /* arm simple, non interrupt dependent timer */
 168                reset_timer_masked ();
 169
 170                if (info->protect[sect] == 0) { /* not protected */
 171                        vu_long *addr = (vu_long *) (info->start[sect]);
 172
 173                        *addr = 0x00200020;     /* erase setup */
 174                        *addr = 0x00D000D0;     /* erase confirm */
 175
 176                        while ((*addr & 0x00800080) != 0x00800080) {
 177                                if (get_timer_masked () >
 178                                    CONFIG_SYS_FLASH_ERASE_TOUT) {
 179                                        *addr = 0x00B000B0;     /* suspend erase */
 180                                        *addr = 0x00FF00FF;     /* reset to read mode */
 181                                        rc = ERR_TIMOUT;
 182                                        goto outahere;
 183                                }
 184                        }
 185
 186                        *addr = 0x00FF00FF;     /* reset to read mode */
 187                }
 188                printf ("ok.\n");
 189        }
 190        if (ctrlc ())
 191                printf ("User Interrupt!\n");
 192
 193      outahere:
 194
 195        /* allow flash to settle - wait 10 ms */
 196        udelay_masked (10000);
 197
 198        if (flag)
 199                enable_interrupts ();
 200
 201        return rc;
 202}
 203
 204/*-----------------------------------------------------------------------
 205 * Copy memory to flash
 206 */
 207
 208static int write_word (flash_info_t * info, ulong dest, ulong data)
 209{
 210        vu_long *addr = (vu_long *) dest;
 211        ulong barf;
 212        int rc = ERR_OK;
 213        int flag;
 214
 215        /* Check if Flash is (sufficiently) erased
 216         */
 217        if ((*addr & data) != data)
 218                return ERR_NOT_ERASED;
 219
 220        /*
 221         * Disable interrupts which might cause a timeout
 222         * here. Remember that our exception vectors are
 223         * at address 0 in the flash, and we don't want a
 224         * (ticker) exception to happen while the flash
 225         * chip is in programming mode.
 226         */
 227        flag = disable_interrupts ();
 228
 229        /* clear status register command */
 230        *addr = 0x00500050;
 231
 232        /* program set-up command */
 233        *addr = 0x00400040;
 234
 235        /* latch address/data */
 236        *addr = data;
 237
 238        /* arm simple, non interrupt dependent timer */
 239        reset_timer_masked ();
 240
 241        /* read status register command */
 242        *addr = 0x00700070;
 243
 244        /* wait while polling the status register */
 245        while ((*addr & 0x00800080) != 0x00800080) {
 246                if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) {
 247                        rc = ERR_TIMOUT;
 248                        /* suspend program command */
 249                        *addr = 0x00B000B0;
 250                        goto outahere;
 251                }
 252
 253                if (*addr & 0x003A003A) {       /* check for error */
 254                        barf = *addr;
 255                        if (barf & 0x003A0000) {
 256                                barf >>= 16;
 257                        } else {
 258                                barf &= 0x0000003A;
 259                        }
 260                        printf ("\nFlash write error %02lx at address %08lx\n", barf, (unsigned long) dest);
 261                        if (barf & 0x0002) {
 262                                printf ("Block locked, not erased.\n");
 263                                rc = ERR_NOT_ERASED;
 264                                goto outahere;
 265                        }
 266                        if (barf & 0x0010) {
 267                                printf ("Programming error.\n");
 268                                rc = ERR_PROG_ERROR;
 269                                goto outahere;
 270                        }
 271                        if (barf & 0x0008) {
 272                                printf ("Vpp Low error.\n");
 273                                rc = ERR_PROG_ERROR;
 274                                goto outahere;
 275                        }
 276                        rc = ERR_PROG_ERROR;
 277                        goto outahere;
 278                }
 279        }
 280
 281
 282      outahere:
 283        /* read array command */
 284        *addr = 0x00FF00FF;
 285
 286        if (flag)
 287                enable_interrupts ();
 288
 289        return rc;
 290}
 291
 292/*-----------------------------------------------------------------------
 293 * Copy memory to flash.
 294 */
 295
 296int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 297{
 298        ulong cp, wp, data;
 299        int l;
 300        int i, rc;
 301
 302        wp = (addr & ~3);       /* get lower word aligned address */
 303
 304        /*
 305         * handle unaligned start bytes
 306         */
 307        if ((l = addr - wp) != 0) {
 308                data = 0;
 309                for (i = 0, cp = wp; i < l; ++i, ++cp) {
 310                        data = (data >> 8) | (*(uchar *) cp << 24);
 311                }
 312                for (; i < 4 && cnt > 0; ++i) {
 313                        data = (data >> 8) | (*src++ << 24);
 314                        --cnt;
 315                        ++cp;
 316                }
 317                for (; cnt == 0 && i < 4; ++i, ++cp) {
 318                        data = (data >> 8) | (*(uchar *) cp << 24);
 319                }
 320
 321                if ((rc = write_word (info, wp, data)) != 0) {
 322                        return (rc);
 323                }
 324                wp += 4;
 325        }
 326
 327        /*
 328         * handle word aligned part
 329         */
 330        while (cnt >= 4) {
 331                data = *((vu_long *) src);
 332                if ((rc = write_word (info, wp, data)) != 0) {
 333                        return (rc);
 334                }
 335                src += 4;
 336                wp += 4;
 337                cnt -= 4;
 338        }
 339
 340        if (cnt == 0) {
 341                return ERR_OK;
 342        }
 343
 344        /*
 345         * handle unaligned tail bytes
 346         */
 347        data = 0;
 348        for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
 349                data = (data >> 8) | (*src++ << 24);
 350                --cnt;
 351        }
 352        for (; i < 4; ++i, ++cp) {
 353                data = (data >> 8) | (*(uchar *) cp << 24);
 354        }
 355
 356        return write_word (info, wp, data);
 357}
 358