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