uboot/board/modnet50/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * MAZeT GmbH <www.mazet.de>
   4 * Stephan Linz <linz@mazet.de>, <linz@li-pro.net>
   5 *
   6 * The most stuff comes from PPCBoot and Linux.
   7 *
   8 * IMMS gGmbH <www.imms.de>
   9 * Thomas Elste <info@elste.org>
  10 *
  11 * Modifications for ModNET50 Board
  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#include <common.h>
  33#include <asm/arch/netarm_registers.h>
  34
  35#define SCR   (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_SYSTEM_CONTROL))
  36
  37#define ALIGN_ABORT_OFF         SCR = SCR & ~NETARM_GEN_SYS_CFG_ALIGN_ABORT
  38#define ALIGN_ABORT_ON          SCR = SCR |  NETARM_GEN_SYS_CFG_ALIGN_ABORT
  39
  40#define PROG_ADDR               (0x555*2)
  41#define SETUP_ADDR              (0x555*2)
  42#define ID_ADDR                 (0x555*2)
  43#define UNLOCK_ADDR1            (0x555*2)
  44#define UNLOCK_ADDR2            (0x2AA*2)
  45
  46#define UNLOCK_CMD1             (0xAA)
  47#define UNLOCK_CMD2             (0x55)
  48#define ERASE_SUSPEND_CMD       (0xB0)
  49#define ERASE_RESUME_CMD        (0x30)
  50#define RESET_CMD               (0xF0)
  51#define ID_CMD                  (0x90)
  52#define SECERASE_CMD            (0x30)
  53#define CHIPERASE_CMD           (0x10)
  54#define PROG_CMD                (0xa0)
  55#define SETUP_CMD               (0x80)
  56
  57#define DQ2                     (0x04)
  58#define DQ3                     (DQ2*2)
  59#define DQ5                     (DQ3*4)
  60#define DQ6                     (DQ5*2)
  61
  62#define WRITE_UNLOCK(addr) { \
  63  *(volatile __u16*)(addr + UNLOCK_ADDR1) = (__u16)UNLOCK_CMD1; \
  64  *(volatile __u16*)(addr + UNLOCK_ADDR2) = (__u16)UNLOCK_CMD2; \
  65}
  66
  67#define CONFIG_AM29_RESERVED    (0)
  68#define K                       (1024)
  69#define MB                      (4)
  70
  71#define CELL_SIZE               (64*K)
  72#define DEVICE_SIZE             (MB*K*K)
  73#define CELLS_PER_DEVICE        (DEVICE_SIZE/CELL_SIZE)
  74#define RESERVED_CELLS          (CONFIG_AM29_RESERVED*K)/CELL_SIZE
  75#define MAX_FLASH_DEVICES       (1)
  76#define AVAIL_SIZE              (DEVICE_SIZE*MAX_FLASH_DEVICES - RESERVED_CELLS*CELL_SIZE)
  77
  78
  79flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  80static __u16 toggling_bits;
  81
  82
  83/*-----------------------------------------------------------------------
  84 */
  85ulong flash_get_size (ulong baseaddr, flash_info_t * info)
  86{
  87        short i;
  88        __u16 flashtest;
  89
  90        /* Write auto select command sequence and test FLASH answer */
  91        WRITE_UNLOCK (baseaddr);
  92        *(volatile __u16 *) (baseaddr + ID_ADDR) = (__u16) ID_CMD;
  93        flashtest /* manufacturer ID */  = *(volatile __u16 *) (baseaddr);
  94        *(volatile __u16 *) (baseaddr + ID_ADDR) = (__u16) RESET_CMD;
  95
  96        switch ((__u32) ((flashtest << 16) + flashtest)) {
  97        case AMD_MANUFACT:
  98                info->flash_id = FLASH_MAN_AMD & FLASH_VENDMASK;
  99                break;
 100        case FUJ_MANUFACT:
 101                info->flash_id = FLASH_MAN_FUJ & FLASH_VENDMASK;
 102                break;
 103        default:
 104                info->flash_id = FLASH_UNKNOWN;
 105                info->sector_count = 0;
 106                info->size = 0;
 107                return (0);     /* no or unknown flash */
 108        }
 109
 110        /* Write auto select command sequence and test FLASH answer */
 111        WRITE_UNLOCK (baseaddr);
 112        *(volatile __u16 *) (baseaddr + ID_ADDR) = (__u16) ID_CMD;
 113        flashtest /* device ID */  = *(volatile __u16 *) (baseaddr + 2);
 114        *(volatile __u16 *) (baseaddr + ID_ADDR) = (__u16) RESET_CMD;
 115
 116        /* toggling_bits = (flashtest == TOSHIBA)?(DQ6):(DQ2|DQ6); */
 117        toggling_bits = (DQ2 | DQ6);
 118
 119        switch ((__u32) ((flashtest << 16) + flashtest)) {
 120        case AMD_ID_LV160B:
 121                info->flash_id +=
 122                        (FLASH_AM160LV | FLASH_AM160B) & FLASH_TYPEMASK;
 123                info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 124                info->size = CONFIG_SYS_FLASH_SIZE;
 125                /* 1*16K Boot Block
 126                   2*8K Parameter Block
 127                   1*32K Small Main Block */
 128                info->start[0] = baseaddr;
 129                info->start[1] = baseaddr + 0x4000;
 130                info->start[2] = baseaddr + 0x6000;
 131                info->start[3] = baseaddr + 0x8000;
 132                for (i = 1; i < info->sector_count; i++)
 133                        info->start[3 + i] = baseaddr + i * CONFIG_SYS_MAIN_SECT_SIZE;
 134                break;
 135        default:
 136                info->flash_id = FLASH_UNKNOWN;
 137                return (0);     /* no or unknown flash */
 138        }
 139
 140        for (i = 0; i < info->sector_count; i++) {
 141                /* Write auto select command sequence and test FLASH answer */
 142                WRITE_UNLOCK (info->start[i]);
 143                *(volatile __u16 *) (info->start[i] + ID_ADDR) = (__u16) ID_CMD;
 144                flashtest /* protected verify */  = *(volatile __u16 *) (info->start[i] + 4);
 145                *(volatile __u16 *) (info->start[i] + ID_ADDR) = (__u16) RESET_CMD;
 146                if (flashtest & 0x0001) {
 147                        info->protect[i] = 1;   /* D0 = 1 if protected */
 148                } else {
 149                        info->protect[i] = 0;
 150                }
 151        }
 152        return (info->size);
 153}
 154
 155/*-----------------------------------------------------------------------
 156 */
 157ulong flash_init (void)
 158{
 159        ulong size = 0;
 160        int i;
 161
 162        /* Init: no FLASHes known */
 163        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
 164                flash_info[i].flash_id = FLASH_UNKNOWN;
 165        }
 166
 167        /* Static FLASH Bank configuration here (only one bank) */
 168        size = flash_get_size (CONFIG_SYS_FLASH_BASE, &flash_info[0]);
 169
 170        if (flash_info[0].flash_id == FLASH_UNKNOWN || size == 0) {
 171                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
 172                        size, size >> 20);
 173        }
 174
 175        /*
 176         * protect monitor and environment sectors
 177         */
 178        flash_protect (FLAG_PROTECT_SET,
 179                       CONFIG_SYS_FLASH_BASE,
 180                       CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
 181                       &flash_info[0]);
 182
 183        flash_protect (FLAG_PROTECT_SET,
 184                       CONFIG_ENV_ADDR,
 185                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0]);
 186
 187        return size;
 188}
 189
 190/*-----------------------------------------------------------------------
 191 */
 192void flash_print_info (flash_info_t * info)
 193{
 194        int i;
 195
 196        if (info->flash_id == FLASH_UNKNOWN) {
 197                printf ("missing or unknown FLASH type\n");
 198                return;
 199        }
 200
 201        switch (info->flash_id & FLASH_VENDMASK) {
 202        case FLASH_MAN_AMD:
 203                printf ("AMD ");
 204                break;
 205        case FLASH_MAN_FUJ:
 206                printf ("Fujitsu ");
 207                break;
 208        default:
 209                printf ("Unknown Vendor ");
 210                break;
 211        }
 212
 213        switch (info->flash_id & FLASH_TYPEMASK) {
 214        case FLASH_AMDL323B:
 215                printf ("29DL323B (32 M, bottom sector)\n");
 216                break;
 217        case (FLASH_AM160LV | FLASH_AM160B):
 218                printf ("29LV160BE (1M x 16, bottom sector)\n");
 219                break;
 220        default:
 221                printf ("Unknown Chip Type\n");
 222                break;
 223        }
 224
 225        printf ("  Size: %ld MB in %d Sectors\n",
 226                info->size >> 20, info->sector_count);
 227        printf ("  Sector Start Addresses:");
 228        for (i = 0; i < info->sector_count; i++) {
 229                if ((i % 4) == 0)
 230                        printf ("\n   ");
 231                printf (" S%02d @ 0x%08lX%s", i,
 232                        info->start[i], info->protect[i] ? " !" : "  ");
 233        }
 234        printf ("\n");
 235        return;
 236}
 237
 238/*-----------------------------------------------------------------------
 239 */
 240int flash_check_protection (flash_info_t * info, int s_first, int s_last)
 241{
 242        int sect, prot = 0;
 243
 244        for (sect = s_first; sect <= s_last; sect++)
 245                if (info->protect[sect])
 246                        prot++;
 247        if (prot)
 248                printf ("- can't erase %d protected sectors\n", prot);
 249        return prot;
 250}
 251
 252/*-----------------------------------------------------------------------
 253 */
 254int flash_check_erase_amd (ulong start)
 255{
 256        __u16 v1, v2;
 257
 258        v1 = *(volatile __u16 *) (start);
 259        v2 = *(volatile __u16 *) (start);
 260
 261        if (((v1 ^ v2) & toggling_bits) == toggling_bits) {
 262                if (((v1 | v2) & DQ5) == DQ5) {
 263                        printf ("[DQ5] ");
 264                        /* OOPS: exceeded timing limits */
 265
 266                        v1 = *(volatile __u16 *) (start);
 267                        v2 = *(volatile __u16 *) (start);
 268
 269                        if (((v1 ^ v2) & toggling_bits) == toggling_bits) {
 270
 271                                printf ("[%s] ",
 272                                        ((toggling_bits & (DQ2 | DQ6)) ==
 273                                         (DQ2 | DQ6)) ? "DQ2,DQ6" : "DQ6");
 274
 275                                /* OOPS: there is an erasure in progress,
 276                                 *       try to reset chip */
 277                                *(volatile __u16 *) (start) =
 278                                        (__u16) RESET_CMD;
 279
 280                                return 1;       /* still busy */
 281                        }
 282                }
 283                return 1;       /* still busy */
 284        }
 285        return 0;               /* be free */
 286}
 287
 288/*-----------------------------------------------------------------------
 289 */
 290int flash_erase (flash_info_t * info, int s_first, int s_last)
 291{
 292        int flag, sect, setup_offset = 0;
 293        int rc = ERR_OK;
 294
 295        if (info->flash_id == FLASH_UNKNOWN) {
 296                printf ("- missing\n");
 297                return ERR_UNKNOWN_FLASH_TYPE;
 298        }
 299
 300        if ((s_first < 0) || (s_first > s_last)) {
 301                printf ("- no sectors to erase\n");
 302                return ERR_INVAL;
 303        }
 304
 305        if (flash_check_protection (info, s_first, s_last))
 306                return ERR_PROTECTED;
 307
 308        switch (info->flash_id & FLASH_VENDMASK) {
 309        case FLASH_MAN_FUJ:
 310        case FLASH_MAN_AMD:
 311                switch (info->flash_id & FLASH_TYPEMASK) {
 312                case (FLASH_AM160LV | FLASH_AM160B):
 313                        setup_offset = UNLOCK_ADDR1;    /* just the adress for setup_cmd differs */
 314                case FLASH_AMDL323B:
 315                        /*
 316                         * Disable interrupts which might cause a timeout
 317                         * here. Remember that our exception vectors are
 318                         * at address 0 in the flash, and we don't want a
 319                         * (ticker) exception to happen while the flash
 320                         * chip is in programming mode.
 321                         */
 322                        flag = disable_interrupts ();
 323                        /* Start erase on unprotected sectors */
 324                        for (sect = s_first; sect <= s_last && !ctrlc ();
 325                             sect++) {
 326                                printf ("Erasing sector %2d ... ", sect);
 327
 328                                if (info->protect[sect] == 0) {
 329                                        /* not protected */
 330                                        /* Write sector erase command sequence */
 331                                        WRITE_UNLOCK (info->start[0]);
 332                                        *(volatile __u16 *) (info->start[0] +
 333                                                             setup_offset) =
 334                                                (__u16) SETUP_CMD;
 335                                        WRITE_UNLOCK (info->start[0]);
 336                                        *(volatile __u16 *) (info->
 337                                                             start[sect]) =
 338                                                (__u16) SECERASE_CMD;
 339
 340                                        /* wait some time */
 341                                        reset_timer_masked ();
 342                                        while (get_timer_masked () < 1000) {
 343                                        }
 344
 345                                        /* arm simple, non interrupt dependent timer */
 346                                        reset_timer_masked ();
 347                                        while (flash_check_erase_amd (info->start[sect])) {
 348                                                if (get_timer_masked () > CONFIG_SYS_FLASH_ERASE_TOUT) {
 349                                                        printf ("timeout!\n");
 350                                                        /* OOPS: reach timeout,
 351                                                         * try to reset chip
 352                                                         */
 353                                                        *(volatile __u16 *) (info-> start[sect]) = (__u16) RESET_CMD;
 354                                                        rc = ERR_TIMOUT;
 355                                                        goto outahere_323B;
 356                                                }
 357                                        }
 358                                        printf ("ok.\n");
 359                                } else {
 360                                        printf ("protected!\n");
 361                                }
 362                        }
 363                        if (ctrlc ())
 364                                printf ("User Interrupt!\n");
 365outahere_323B:
 366                        /* allow flash to settle - wait 10 ms */
 367                        udelay_masked (10000);
 368                        if (flag)
 369                                enable_interrupts ();
 370                        return rc;
 371                default:
 372                        printf ("- unknown chip type\n");
 373                        return ERR_UNKNOWN_FLASH_TYPE;
 374                }
 375                break;
 376        default:
 377                printf ("- unknown vendor ");
 378                return ERR_UNKNOWN_FLASH_VENDOR;
 379        }
 380}
 381
 382/*-----------------------------------------------------------------------
 383 */
 384int flash_check_write_amd (ulong dest)
 385{
 386        __u16 v1, v2;
 387
 388        v1 = *(volatile __u16 *) (dest);
 389        v2 = *(volatile __u16 *) (dest);
 390
 391        /* DQ6 toggles during write */
 392        if (((v1 ^ v2) & DQ6) == DQ6) {
 393                if (((v1 | v2) & DQ5) == DQ5) {
 394                        printf ("[DQ5] @ %08lX\n", dest);
 395
 396                        /* OOPS: exceeded timing limits,
 397                         *       try to reset chip */
 398                        *(volatile __u16 *) (dest) = (__u16) RESET_CMD;
 399                        return 0;       /* be free */
 400                }
 401                return 1;       /* still busy */
 402        }
 403
 404        return 0;               /* be free */
 405}
 406
 407/*-----------------------------------------------------------------------
 408 * Copy memory to flash
 409 */
 410static int write_word (flash_info_t * info, ulong dest, ushort data)
 411{
 412        int rc = ERR_OK;
 413        int flag;
 414
 415        /* Check if Flash is (sufficiently) erased */
 416        if ((*(__u16 *) (dest) & data) != data)
 417                return ERR_NOT_ERASED;
 418
 419        /*
 420         * Disable interrupts which might cause a timeout
 421         * here. Remember that our exception vectors are
 422         * at address 0 in the flash, and we don't want a
 423         * (ticker) exception to happen while the flash
 424         * chip is in programming mode.
 425         */
 426        flag = disable_interrupts ();
 427
 428        /* Write program command sequence */
 429        WRITE_UNLOCK (info->start[0]);
 430
 431        /* Flash dependend program seqence */
 432        switch (info->flash_id & FLASH_VENDMASK) {
 433        case FLASH_MAN_FUJ:
 434        case FLASH_MAN_AMD:
 435                switch (info->flash_id & FLASH_TYPEMASK) {
 436                case (FLASH_AM160LV | FLASH_AM160B):
 437                        *(volatile __u16 *) (info->start[0] + UNLOCK_ADDR1) =
 438                                (__u16) PROG_CMD;
 439                        *(volatile __u16 *) (dest) = (__u16) data;
 440                        break;
 441                case FLASH_AMDL323B:
 442                        *(volatile __u16 *) (dest) = (__u16) PROG_CMD;
 443                        *(volatile __u16 *) (dest) = (__u16) data;
 444                        break;
 445                }
 446        }
 447
 448        /* arm simple, non interrupt dependent timer */
 449        reset_timer_masked ();
 450
 451        while (flash_check_write_amd (dest)) {
 452                if (get_timer_masked () > CONFIG_SYS_FLASH_WRITE_TOUT) {
 453                        printf ("timeout! @ %08lX\n", dest);
 454                        /* OOPS: reach timeout,
 455                         *       try to reset chip */
 456                        *(volatile __u16 *) (dest) = (__u16) RESET_CMD;
 457
 458                        rc = ERR_TIMOUT;
 459                        goto outahere_323B;
 460                }
 461        }
 462
 463        /* Check if Flash was (accurately) written */
 464        if (*(__u16 *) (dest) != data)
 465                rc = ERR_PROG_ERROR;
 466
 467outahere_323B:
 468        if (flag)
 469                enable_interrupts ();
 470        return rc;
 471}
 472
 473/*-----------------------------------------------------------------------
 474 * Copy memory to flash.
 475 */
 476int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 477{
 478        ulong cp, wp;
 479        ushort data;
 480        int l;
 481        int i, rc;
 482
 483        wp = (addr & ~1);       /* get lower word aligned address */
 484
 485        /*
 486         * handle unaligned start bytes
 487         */
 488        if ((l = addr - wp) != 0) {
 489                data = 0;
 490                for (i = 0, cp = wp; i < l; ++i, ++cp) {
 491                        data = (data >> 8) | (*(uchar *) cp << 8);
 492                }
 493                for (; i < 2 && cnt > 0; ++i) {
 494                        data = (data >> 8) | (*src++ << 8);
 495                        --cnt;
 496                        ++cp;
 497                }
 498                for (; cnt == 0 && i < 2; ++i, ++cp) {
 499                        data = (data >> 8) | (*(uchar *) cp << 8);
 500                }
 501
 502                if ((rc = write_word (info, wp, data)) != 0) {
 503                        return (rc);
 504                }
 505                wp += 2;
 506        }
 507
 508        /*
 509         * handle word aligned part
 510         */
 511        while (cnt >= 2) {
 512                data = *((ushort *) src);
 513                if ((rc = write_word (info, wp, data)) != 0)
 514                        return (rc);
 515                src += 2;
 516                wp += 2;
 517                cnt -= 2;
 518        }
 519
 520        if (cnt == 0)
 521                return ERR_OK;
 522
 523        /*
 524         * handle unaligned tail bytes
 525         */
 526        data = 0;
 527        for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
 528                data = (data >> 8) | (*src++ << 8);
 529                --cnt;
 530        }
 531        for (; i < 2; ++i, ++cp) {
 532                data = (data >> 8) | (*(uchar *) cp << 8);
 533        }
 534
 535        return write_word (info, wp, data);
 536}
 537