uboot/board/shannon/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   4 * Alex Zuepke <azu@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
  27ulong myflush(void);
  28
  29
  30#define FLASH_BANK_SIZE 0x400000        /* 4 MB */
  31#define MAIN_SECT_SIZE  0x20000         /* 128 KB */
  32
  33flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  34
  35
  36#define CMD_READ_ARRAY          0x00F000F0
  37#define CMD_UNLOCK1             0x00AA00AA
  38#define CMD_UNLOCK2             0x00550055
  39#define CMD_ERASE_SETUP         0x00800080
  40#define CMD_ERASE_CONFIRM       0x00300030
  41#define CMD_PROGRAM             0x00A000A0
  42#define CMD_UNLOCK_BYPASS       0x00200020
  43
  44#define MEM_FLASH_ADDR1         (*(volatile u32 *)(CONFIG_SYS_FLASH_BASE + (0x00000555 << 2)))
  45#define MEM_FLASH_ADDR2         (*(volatile u32 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA << 2)))
  46
  47#define BIT_ERASE_DONE          0x00800080
  48#define BIT_RDY_MASK            0x00800080
  49#define BIT_PROGRAM_ERROR       0x00200020
  50#define BIT_TIMEOUT             0x80000000 /* our flag */
  51
  52#define READY 1
  53#define ERR   2
  54#define TMO   4
  55
  56/*-----------------------------------------------------------------------
  57 */
  58
  59ulong flash_init(void)
  60{
  61    int i, j;
  62    ulong size = 0;
  63
  64    for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
  65    {
  66        ulong flashbase = 0;
  67        flash_info[i].flash_id =
  68          (AMD_MANUFACT & FLASH_VENDMASK) |
  69          (AMD_ID_LV160B & FLASH_TYPEMASK);
  70        flash_info[i].size = FLASH_BANK_SIZE;
  71        flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
  72        memset(flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
  73        if (i == 0)
  74          flashbase = PHYS_FLASH_1;
  75        else
  76          panic("configured too many flash banks!\n");
  77        for (j = 0; j < flash_info[i].sector_count; j++)
  78        {
  79
  80            if (j <= 3)
  81            {
  82                /* 1st one is 32 KB */
  83                if (j == 0)
  84                {
  85                        flash_info[i].start[j] = flashbase + 0;
  86                }
  87
  88                /* 2nd and 3rd are both 16 KB */
  89                if ((j == 1) || (j == 2))
  90                {
  91                        flash_info[i].start[j] = flashbase + 0x8000 + (j-1)*0x4000;
  92                }
  93
  94                /* 4th 64 KB */
  95                if (j == 3)
  96                {
  97                        flash_info[i].start[j] = flashbase + 0x10000;
  98                }
  99            }
 100            else
 101            {
 102                flash_info[i].start[j] = flashbase + (j - 3)*MAIN_SECT_SIZE;
 103            }
 104        }
 105        size += flash_info[i].size;
 106    }
 107
 108    /*
 109     * Protect monitor and environment sectors
 110     * Inferno is complicated, it's hardware locked
 111     */
 112#ifdef CONFIG_INFERNO
 113    /* first one, 0x00000 to 0x07fff */
 114    flash_protect(FLAG_PROTECT_SET,
 115                  CONFIG_SYS_FLASH_BASE + 0x00000,
 116                  CONFIG_SYS_FLASH_BASE + 0x08000 - 1,
 117                  &flash_info[0]);
 118
 119    /* third to 10th, 0x0c000 - 0xdffff */
 120    flash_protect(FLAG_PROTECT_SET,
 121                  CONFIG_SYS_FLASH_BASE + 0x0c000,
 122                  CONFIG_SYS_FLASH_BASE + 0xe0000 - 1,
 123                  &flash_info[0]);
 124#else
 125    flash_protect(FLAG_PROTECT_SET,
 126                  CONFIG_SYS_FLASH_BASE,
 127                  CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
 128                  &flash_info[0]);
 129
 130    flash_protect(FLAG_PROTECT_SET,
 131                  CONFIG_ENV_ADDR,
 132                  CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
 133                  &flash_info[0]);
 134#endif
 135    return size;
 136}
 137
 138/*-----------------------------------------------------------------------
 139 */
 140void flash_print_info  (flash_info_t *info)
 141{
 142    int i;
 143
 144    switch (info->flash_id & FLASH_VENDMASK)
 145    {
 146    case (AMD_MANUFACT & FLASH_VENDMASK):
 147        printf("AMD: ");
 148        break;
 149    default:
 150        printf("Unknown Vendor ");
 151        break;
 152    }
 153
 154    switch (info->flash_id & FLASH_TYPEMASK)
 155    {
 156    case (AMD_ID_LV160B & FLASH_TYPEMASK):
 157        printf("2x Amd29F160BB (16Mbit)\n");
 158        break;
 159    default:
 160        printf("Unknown Chip Type\n");
 161        goto Done;
 162        break;
 163    }
 164
 165    printf("  Size: %ld MB in %d Sectors\n",
 166           info->size >> 20, info->sector_count);
 167
 168    printf("  Sector Start Addresses:");
 169    for (i = 0; i < info->sector_count; i++)
 170    {
 171        if ((i % 5) == 0)
 172        {
 173            printf ("\n   ");
 174        }
 175        printf (" %08lX%s", info->start[i],
 176                info->protect[i] ? " (RO)" : "     ");
 177    }
 178    printf ("\n");
 179
 180Done:
 181    ;
 182}
 183
 184/*-----------------------------------------------------------------------
 185 */
 186
 187int     flash_erase (flash_info_t *info, int s_first, int s_last)
 188{
 189    ulong result;
 190    int iflag, cflag, prot, sect;
 191    int rc = ERR_OK;
 192    int chip1, chip2;
 193
 194    /* first look for protection bits */
 195
 196    if (info->flash_id == FLASH_UNKNOWN)
 197        return ERR_UNKNOWN_FLASH_TYPE;
 198
 199    if ((s_first < 0) || (s_first > s_last)) {
 200        return ERR_INVAL;
 201    }
 202
 203    if ((info->flash_id & FLASH_VENDMASK) !=
 204        (AMD_MANUFACT & FLASH_VENDMASK)) {
 205        return ERR_UNKNOWN_FLASH_VENDOR;
 206    }
 207
 208    prot = 0;
 209    for (sect=s_first; sect<=s_last; ++sect) {
 210        if (info->protect[sect]) {
 211            prot++;
 212        }
 213    }
 214    if (prot)
 215        return ERR_PROTECTED;
 216
 217    /*
 218     * Disable interrupts which might cause a timeout
 219     * here. Remember that our exception vectors are
 220     * at address 0 in the flash, and we don't want a
 221     * (ticker) exception to happen while the flash
 222     * chip is in programming mode.
 223     */
 224    cflag = icache_status();
 225    icache_disable();
 226    iflag = disable_interrupts();
 227
 228    /* Start erase on unprotected sectors */
 229    for (sect = s_first; sect<=s_last && !ctrlc(); sect++)
 230    {
 231        printf("Erasing sector %2d ... ", sect);
 232
 233        /* arm simple, non interrupt dependent timer */
 234        reset_timer_masked();
 235
 236        if (info->protect[sect] == 0)
 237        {       /* not protected */
 238            vu_long *addr = (vu_long *)(info->start[sect]);
 239
 240            MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 241            MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 242            MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
 243
 244            MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 245            MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 246            *addr = CMD_ERASE_CONFIRM;
 247
 248            /* wait until flash is ready */
 249            chip1 = chip2 = 0;
 250
 251            do
 252            {
 253                result = *addr;
 254
 255                /* check timeout */
 256                if (get_timer_masked() > CONFIG_SYS_FLASH_ERASE_TOUT)
 257                {
 258                    MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
 259                    chip1 = TMO;
 260                    break;
 261                }
 262
 263                if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE)
 264                        chip1 = READY;
 265
 266                if (!chip1 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
 267                        chip1 = ERR;
 268
 269                if (!chip2 && (result >> 16) & BIT_ERASE_DONE)
 270                        chip2 = READY;
 271
 272                if (!chip2 && (result >> 16) & BIT_PROGRAM_ERROR)
 273                        chip2 = ERR;
 274
 275            }  while (!chip1 || !chip2);
 276
 277            MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
 278
 279            if (chip1 == ERR || chip2 == ERR)
 280            {
 281                rc = ERR_PROG_ERROR;
 282                goto outahere;
 283            }
 284            if (chip1 == TMO)
 285            {
 286                rc = ERR_TIMOUT;
 287                goto outahere;
 288            }
 289
 290            printf("ok.\n");
 291        }
 292        else /* it was protected */
 293        {
 294            printf("protected!\n");
 295        }
 296    }
 297
 298    if (ctrlc())
 299      printf("User Interrupt!\n");
 300
 301outahere:
 302    /* allow flash to settle - wait 10 ms */
 303    udelay_masked(10000);
 304
 305    if (iflag)
 306      enable_interrupts();
 307
 308    if (cflag)
 309      icache_enable();
 310
 311    return rc;
 312}
 313
 314/*-----------------------------------------------------------------------
 315 * Copy memory to flash
 316 */
 317
 318static int write_word (flash_info_t *info, ulong dest, ulong data)
 319{
 320    vu_long *addr = (vu_long *)dest;
 321    ulong result;
 322    int rc = ERR_OK;
 323    int cflag, iflag;
 324    int chip1, chip2;
 325
 326    /*
 327     * Check if Flash is (sufficiently) erased
 328     */
 329    result = *addr;
 330    if ((result & data) != data)
 331        return ERR_NOT_ERASED;
 332
 333
 334    /*
 335     * Disable interrupts which might cause a timeout
 336     * here. Remember that our exception vectors are
 337     * at address 0 in the flash, and we don't want a
 338     * (ticker) exception to happen while the flash
 339     * chip is in programming mode.
 340     */
 341    cflag = icache_status();
 342    icache_disable();
 343    iflag = disable_interrupts();
 344
 345    MEM_FLASH_ADDR1 = CMD_UNLOCK1;
 346    MEM_FLASH_ADDR2 = CMD_UNLOCK2;
 347    MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
 348    *addr = CMD_PROGRAM;
 349    *addr = data;
 350
 351    /* arm simple, non interrupt dependent timer */
 352    reset_timer_masked();
 353
 354    /* wait until flash is ready */
 355    chip1 = chip2 = 0;
 356    do
 357    {
 358        result = *addr;
 359
 360        /* check timeout */
 361        if (get_timer_masked() > CONFIG_SYS_FLASH_ERASE_TOUT)
 362        {
 363            chip1 = ERR | TMO;
 364            break;
 365        }
 366        if (!chip1 && ((result & 0x80) == (data & 0x80)))
 367                chip1 = READY;
 368
 369        if (!chip1 && ((result & 0xFFFF) & BIT_PROGRAM_ERROR))
 370        {
 371                result = *addr;
 372
 373                if ((result & 0x80) == (data & 0x80))
 374                        chip1 = READY;
 375                else
 376                        chip1 = ERR;
 377        }
 378
 379        if (!chip2 && ((result & (0x80 << 16)) == (data & (0x80 << 16))))
 380                chip2 = READY;
 381
 382        if (!chip2 && ((result >> 16) & BIT_PROGRAM_ERROR))
 383        {
 384                result = *addr;
 385
 386                if ((result & (0x80 << 16)) == (data & (0x80 << 16)))
 387                        chip2 = READY;
 388                else
 389                        chip2 = ERR;
 390        }
 391
 392    }  while (!chip1 || !chip2);
 393
 394    *addr = CMD_READ_ARRAY;
 395
 396    if (chip1 == ERR || chip2 == ERR || *addr != data)
 397        rc = ERR_PROG_ERROR;
 398
 399    if (iflag)
 400      enable_interrupts();
 401
 402    if (cflag)
 403      icache_enable();
 404
 405    return rc;
 406}
 407
 408/*-----------------------------------------------------------------------
 409 * Copy memory to flash.
 410 */
 411
 412int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 413{
 414    ulong cp, wp, data;
 415    int l;
 416    int i, rc;
 417
 418    wp = (addr & ~3);   /* get lower word aligned address */
 419
 420    /*
 421     * handle unaligned start bytes
 422     */
 423    if ((l = addr - wp) != 0) {
 424        data = 0;
 425        for (i=0, cp=wp; i<l; ++i, ++cp) {
 426            data = (data >> 8) | (*(uchar *)cp << 24);
 427        }
 428        for (; i<4 && cnt>0; ++i) {
 429            data = (data >> 8) | (*src++ << 24);
 430            --cnt;
 431            ++cp;
 432        }
 433        for (; cnt==0 && i<4; ++i, ++cp) {
 434            data = (data >> 8) | (*(uchar *)cp << 24);
 435        }
 436
 437        if ((rc = write_word(info, wp, data)) != 0) {
 438            return (rc);
 439        }
 440        wp += 4;
 441    }
 442
 443    /*
 444     * handle word aligned part
 445     */
 446    while (cnt >= 4) {
 447        data = *((vu_long*)src);
 448        if ((rc = write_word(info, wp, data)) != 0) {
 449            return (rc);
 450        }
 451        src += 4;
 452        wp  += 4;
 453        cnt -= 4;
 454    }
 455
 456    if (cnt == 0) {
 457        return ERR_OK;
 458    }
 459
 460    /*
 461     * handle unaligned tail bytes
 462     */
 463    data = 0;
 464    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 465        data = (data >> 8) | (*src++ << 24);
 466        --cnt;
 467    }
 468    for (; i<4; ++i, ++cp) {
 469        data = (data >> 8) | (*(uchar *)cp << 24);
 470    }
 471
 472    return write_word(info, wp, data);
 473}
 474