uboot/board/mvblue/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 * (C) Copyright 2001-2003
   5 *
   6 * Changes for MATRIX Vision mvBLUE devices
   7 * MATRIX Vision GmbH / hg,as info@matrix-vision.de
   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#include <mpc824x.h>
  27
  28#if 0
  29        #define mvdebug(p) printf ##p
  30#else
  31        #define mvdebug(p)
  32#endif
  33
  34flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  35
  36#define FLASH_BUS_WIDTH         8
  37
  38#if (FLASH_BUS_WIDTH==32)
  39        #define FLASH_DATA_MASK 0xffffffff
  40        #define FLASH_SHIFT 1
  41        #define FDT     vu_long
  42#elif (FLASH_BUS_WIDTH==16)
  43        #define FLASH_DATA_MASK 0xff
  44        #define FLASH_SHIFT 0
  45        #define FDT     vu_short
  46#elif (FLASH_BUS_WIDTH==8)
  47        #define FLASH_DATA_MASK 0xff
  48        #define FLASH_SHIFT 0
  49        #define FDT     vu_char
  50#else
  51        #error FLASH_BUS_WIDTH undefined
  52#endif
  53
  54/*-----------------------------------------------------------------------
  55 * Functions
  56 */
  57static ulong flash_get_size (vu_long *address, flash_info_t *info);
  58static int write_word (flash_info_t *info, ulong dest, ulong data);
  59static void flash_get_offsets (ulong base, flash_info_t *info);
  60
  61/*-----------------------------------------------------------------------
  62 */
  63unsigned long flash_init (void)
  64{
  65        unsigned long size_b0;
  66        int i;
  67
  68        for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
  69                flash_info[i].flash_id = FLASH_UNKNOWN;
  70        }
  71
  72        size_b0 = flash_get_size((vu_long *)0xffc00000, &flash_info[0]);
  73
  74        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
  75                printf ("## Unknown FLASH : Size = 0x%08lx = %ld MB\n",
  76                        size_b0, size_b0<<20);
  77        }
  78
  79        flash_get_offsets (0xffc00000, &flash_info[0]);
  80        flash_info[0].size = size_b0;
  81
  82        /* monitor protection OFF by default */
  83        flash_protect ( FLAG_PROTECT_CLEAR, 0xffc00000, 0x2000, flash_info );
  84
  85        return size_b0;
  86}
  87
  88/*-----------------------------------------------------------------------
  89 */
  90static void flash_get_offsets (ulong base, flash_info_t *info)
  91{
  92        int i;
  93
  94        /* set up sector start address table */
  95        if (info->flash_id & FLASH_BTYPE)
  96        {       /* bottom boot sector types - these are the useful ones! */
  97                /* set sector offsets for bottom boot block type */
  98                if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B)
  99                {       /* AMDLV320B has 8 x 8k bottom boot sectors */
 100                        for (i = 0; i < 8; i++)                                                                                         /* +8k          */
 101                                info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT));
 102                        for (; i < info->sector_count; i++)                                                                     /* +64k         */
 103                                info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00070000 << FLASH_SHIFT);
 104                }
 105                else
 106                {       /* other types have 4 bottom boot sectors (16,8,8,32) */
 107                        i = 0;
 108                        info->start[i++] = base +  0x00000000;                                                          /* -            */
 109                        info->start[i++] = base + (0x00004000 << FLASH_SHIFT);                          /* +16k         */
 110                        info->start[i++] = base + (0x00006000 << FLASH_SHIFT);                          /* +8k          */
 111                        info->start[i++] = base + (0x00008000 << FLASH_SHIFT);                          /* +8k          */
 112                        info->start[i++] = base + (0x00010000 << FLASH_SHIFT);                          /* +32k         */
 113                        for (; i < info->sector_count; i++)                                                                     /* +64k         */
 114                                info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT)) - (0x00030000 << FLASH_SHIFT);
 115                }
 116        }
 117        else
 118        {       /* top boot sector types - not so useful */
 119                /* set sector offsets for top boot block type */
 120                if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T)
 121                {       /* AMDLV320T has 8 x 8k top boot sectors */
 122                        for (i = 0; i < info->sector_count - 8; i++)                                            /* +64k         */
 123                                info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT));
 124                        for (; i < info->sector_count; i++)                                                                     /* +8k          */
 125                                info->start[i] = base + (i * (0x00002000 << FLASH_SHIFT));
 126                }
 127                else
 128                {       /* other types have 4 top boot sectors (32,8,8,16) */
 129                        for (i = 0; i < info->sector_count - 4; i++)                                            /* +64k         */
 130                                info->start[i] = base + (i * (0x00010000 << FLASH_SHIFT));
 131
 132                        info->start[i++] = base + info->size - (0x00010000 << FLASH_SHIFT);     /* -32k         */
 133                        info->start[i++] = base + info->size - (0x00008000 << FLASH_SHIFT);     /* -8k          */
 134                        info->start[i++] = base + info->size - (0x00006000 << FLASH_SHIFT);     /* -8k          */
 135                        info->start[i]   = base + info->size - (0x00004000 << FLASH_SHIFT);     /* -16k         */
 136                }
 137        }
 138}
 139
 140/*-----------------------------------------------------------------------
 141 */
 142void flash_print_info  (flash_info_t *info)
 143{
 144        int i;
 145
 146        if (info->flash_id == FLASH_UNKNOWN) {
 147                printf ("missing or unknown FLASH type\n");
 148                return;
 149        }
 150
 151        switch (info->flash_id & FLASH_VENDMASK) {
 152        case FLASH_MAN_AMD:     printf ("AMD ");                break;
 153        case FLASH_MAN_FUJ:     printf ("FUJITSU ");    break;
 154        case FLASH_MAN_STM:     printf ("ST ");                 break;
 155        default:                printf ("Unknown Vendor ");     break;
 156        }
 157
 158        switch (info->flash_id & FLASH_TYPEMASK) {
 159        case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
 160                                break;
 161        case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
 162                                break;
 163        case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
 164                                break;
 165        case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
 166                                break;
 167        case FLASH_STMW320DB:   printf ("M29W320B (32 Mbit, bottom boot sect)\n");
 168                                break;
 169        case FLASH_STMW320DT:   printf ("M29W320T (32 Mbit, top boot sector)\n");
 170                                break;
 171        default:                printf ("Unknown Chip Type\n");
 172                                break;
 173        }
 174
 175        printf ("  Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count);
 176
 177        printf ("  Sector Start Addresses:");
 178        for (i=0; i<info->sector_count; ++i) {
 179                if ((i % 5) == 0)
 180                        printf ("\n   ");
 181                printf (" %08lX%s", info->start[i], info->protect[i] ? " (RO)" : "     ");
 182        }
 183        printf ("\n");
 184}
 185
 186/*
 187 * The following code cannot be run from FLASH!
 188 */
 189
 190#define AMD_ID_LV160T_MVS       (AMD_ID_LV160T & FLASH_DATA_MASK)
 191#define AMD_ID_LV160B_MVS       (AMD_ID_LV160B & FLASH_DATA_MASK)
 192#define AMD_ID_LV320T_MVS       (AMD_ID_LV320T & FLASH_DATA_MASK)
 193#define AMD_ID_LV320B_MVS       (AMD_ID_LV320B & FLASH_DATA_MASK)
 194#define STM_ID_W320DT_MVS       (STM_ID_29W320DT & FLASH_DATA_MASK)
 195#define STM_ID_W320DB_MVS       (STM_ID_29W320DB & FLASH_DATA_MASK)
 196#define AMD_MANUFACT_MVS        (AMD_MANUFACT  & FLASH_DATA_MASK)
 197#define FUJ_MANUFACT_MVS        (FUJ_MANUFACT  & FLASH_DATA_MASK)
 198#define STM_MANUFACT_MVS        (STM_MANUFACT  & FLASH_DATA_MASK)
 199
 200#if (FLASH_BUS_WIDTH >= 16)
 201        #define AUTOSELECT_ADDR1        0x0555
 202        #define AUTOSELECT_ADDR2        0x02AA
 203        #define AUTOSELECT_ADDR3        AUTOSELECT_ADDR1
 204#else
 205        #define AUTOSELECT_ADDR1        0x0AAA
 206        #define AUTOSELECT_ADDR2        0x0555
 207        #define AUTOSELECT_ADDR3        AUTOSELECT_ADDR1
 208#endif
 209
 210#define AUTOSELECT_DATA1        (0x00AA00AA & FLASH_DATA_MASK)
 211#define AUTOSELECT_DATA2        (0x00550055 & FLASH_DATA_MASK)
 212#define AUTOSELECT_DATA3        (0x00900090 & FLASH_DATA_MASK)
 213
 214#define RESET_BANK_DATA         (0x00F000F0 & FLASH_DATA_MASK)
 215
 216
 217static ulong flash_get_size (vu_long *address, flash_info_t *info)
 218{
 219        short i;
 220        FDT value;
 221        FDT *addr = (FDT *)address;
 222
 223        ulong base = (ulong)address;
 224        addr[AUTOSELECT_ADDR1] = AUTOSELECT_DATA1;
 225        addr[AUTOSELECT_ADDR2] = AUTOSELECT_DATA2;
 226        addr[AUTOSELECT_ADDR3] = AUTOSELECT_DATA3;
 227        __asm__ __volatile__("sync");
 228
 229        udelay(180);
 230
 231        value = addr[0];                        /* manufacturer ID      */
 232        switch (value) {
 233        case AMD_MANUFACT_MVS:
 234                info->flash_id = FLASH_MAN_AMD;
 235                break;
 236        case FUJ_MANUFACT_MVS:
 237                info->flash_id = FLASH_MAN_FUJ;
 238                break;
 239        case STM_MANUFACT_MVS:
 240                info->flash_id = FLASH_MAN_STM;
 241                break;
 242        default:
 243                info->flash_id = FLASH_UNKNOWN;
 244                info->sector_count = 0;
 245                info->size = 0;
 246                return (0);                     /* no or unknown flash  */
 247        }
 248#if (FLASH_BUS_WIDTH >= 16)
 249        value = addr[1];                        /* device ID            */
 250#else
 251        value = addr[2];                        /* device ID            */
 252#endif
 253
 254        switch (value) {
 255        case AMD_ID_LV160T_MVS:
 256                info->flash_id += FLASH_AM160T;
 257                info->sector_count = 37;
 258                info->size = (0x00200000 << FLASH_SHIFT);
 259                break;                          /* => 2 or 4 MB         */
 260
 261        case AMD_ID_LV160B_MVS:
 262                info->flash_id += FLASH_AM160B;
 263                info->sector_count = 37;
 264                info->size = (0x00200000 << FLASH_SHIFT);
 265                break;                          /* => 2 or 4 MB         */
 266
 267        case AMD_ID_LV320T_MVS:
 268                info->flash_id += FLASH_AM320T;
 269                info->sector_count = 71;
 270                info->size = (0x00400000 << FLASH_SHIFT);
 271                break;                          /* => 4 or 8 MB         */
 272
 273        case AMD_ID_LV320B_MVS:
 274                info->flash_id += FLASH_AM320B;
 275                info->sector_count = 71;
 276                info->size = (0x00400000 << FLASH_SHIFT);
 277                break;                          /* => 4 or 8MB          */
 278
 279        case STM_ID_W320DT_MVS:
 280                info->flash_id += FLASH_STMW320DT;
 281                info->sector_count = 67;
 282                info->size = (0x00400000 << FLASH_SHIFT);
 283                break;                          /* => 4 or 8 MB         */
 284
 285        case STM_ID_W320DB_MVS:
 286                info->flash_id += FLASH_STMW320DB;
 287                info->sector_count = 67;
 288                info->size = (0x00400000 << FLASH_SHIFT);
 289                break;                          /* => 4 or 8MB          */
 290
 291        default:
 292                info->flash_id = FLASH_UNKNOWN;
 293                return (0);                     /* => no or unknown flash */
 294
 295        }
 296
 297        /* set up sector start address table */
 298        flash_get_offsets (base, info);
 299
 300        /* check for protected sectors */
 301        for (i = 0; i < info->sector_count; i++) {
 302                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
 303                /* D0 = 1 if protected */
 304                addr = (FDT *)(info->start[i]);
 305                info->protect[i] = addr[2] & 1;
 306        }
 307
 308        /*
 309         * Prevent writes to uninitialized FLASH.
 310         */
 311        if (info->flash_id != FLASH_UNKNOWN) {
 312                addr = (FDT *)info->start[0];
 313                *addr = RESET_BANK_DATA;        /* reset bank */
 314        }
 315        return (info->size);
 316}
 317
 318
 319/*-----------------------------------------------------------------------
 320 */
 321
 322#if (FLASH_BUS_WIDTH >= 16)
 323        #define ERASE_ADDR1 0x0555
 324        #define ERASE_ADDR2 0x02AA
 325#else
 326        #define ERASE_ADDR1 0x0AAA
 327        #define ERASE_ADDR2 0x0555
 328#endif
 329
 330#define ERASE_ADDR3 ERASE_ADDR1
 331#define ERASE_ADDR4 ERASE_ADDR1
 332#define ERASE_ADDR5 ERASE_ADDR2
 333
 334#define ERASE_DATA1 (0x00AA00AA & FLASH_DATA_MASK)
 335#define ERASE_DATA2 (0x00550055 & FLASH_DATA_MASK)
 336#define ERASE_DATA3 (0x00800080 & FLASH_DATA_MASK)
 337#define ERASE_DATA4 ERASE_DATA1
 338#define ERASE_DATA5 ERASE_DATA2
 339
 340#define ERASE_SECTOR_DATA       (0x00300030 & FLASH_DATA_MASK)
 341#define ERASE_CHIP_DATA         (0x00100010 & FLASH_DATA_MASK)
 342#define ERASE_CONFIRM_DATA      (0x00800080 & FLASH_DATA_MASK)
 343
 344int     flash_erase (flash_info_t *info, int s_first, int s_last)
 345{
 346        FDT *addr = (FDT *)(info->start[0]);
 347
 348        int prot, sect, l_sect, flag;
 349        ulong start, now, last;
 350
 351        __asm__ __volatile__ ("sync");
 352        addr[0] = 0xf0;
 353        udelay(1000);
 354
 355        printf("\nflash_erase: first = %d @ 0x%08lx\n", s_first, info->start[s_first] );
 356        printf("             last  = %d @ 0x%08lx\n", s_last , info->start[s_last ] );
 357
 358        if ((s_first < 0) || (s_first > s_last)) {
 359                if (info->flash_id == FLASH_UNKNOWN) {
 360                        printf ("- missing\n");
 361                } else {
 362                        printf ("- no sectors to erase\n");
 363                }
 364                return 1;
 365        }
 366
 367        if ((info->flash_id == FLASH_UNKNOWN) || (info->flash_id > FLASH_AMD_COMP)) {
 368                printf ("Can't erase unknown flash type %08lx - aborted\n", info->flash_id);
 369                return 1;
 370        }
 371
 372        prot = 0;
 373        for (sect=s_first; sect<=s_last; ++sect) {
 374                if (info->protect[sect]) {
 375                        prot++;
 376                }
 377        }
 378
 379        if (prot) {
 380                printf ("- Warning: %d protected sectors will not be erased!\n",
 381                        prot);
 382        } else {
 383                printf ("\n");
 384        }
 385
 386        l_sect = -1;
 387
 388        /* Disable interrupts which might cause a timeout here */
 389        flag = disable_interrupts();
 390
 391        addr[ERASE_ADDR1] = ERASE_DATA1;
 392        addr[ERASE_ADDR2] = ERASE_DATA2;
 393        addr[ERASE_ADDR3] = ERASE_DATA3;
 394        addr[ERASE_ADDR4] = ERASE_DATA4;
 395        addr[ERASE_ADDR5] = ERASE_DATA5;
 396
 397        for (sect = s_first; sect <= s_last; sect++) {
 398                if (info->protect[sect] == 0) {
 399                        addr = (FDT *)(info->start[sect]);
 400                        addr[0] = ERASE_SECTOR_DATA;
 401                        l_sect = sect;
 402                }
 403        }
 404
 405        if (flag)
 406                enable_interrupts();
 407
 408        /*
 409         * We wait for the last triggered sector
 410         */
 411        if (l_sect < 0)
 412                goto DONE;
 413
 414        start = get_timer (0);
 415        last  = start;
 416        addr = (FDT *)(info->start[l_sect]);
 417
 418        while ((addr[0] & ERASE_CONFIRM_DATA) != ERASE_CONFIRM_DATA) {
 419                if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 420                        printf ("Timeout\n");
 421                        return 1;
 422                }
 423                /* show that we're waiting */
 424                if ((now - last) > 1000) {      /* every second */
 425                        putc ('.');
 426                        last = now;
 427                }
 428        }
 429
 430DONE:
 431        printf (" done\n");
 432        return 0;
 433}
 434
 435/*-----------------------------------------------------------------------
 436 * Copy memory to flash, returns:
 437 * 0 - OK
 438 * 1 - write timeout
 439 * 2 - Flash not erased
 440 */
 441
 442int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 443{
 444#define BUFF_INC 4
 445        ulong cp, wp, data;
 446        int i, l, rc;
 447
 448        mvdebug (("+write_buff %p ==> 0x%08lx, count = 0x%08lx\n", src, addr, cnt));
 449
 450        wp = (addr & ~3);       /* get lower word aligned address */
 451        /*
 452         * handle unaligned start bytes
 453         */
 454        if ((l = addr - wp) != 0) {
 455                mvdebug ((" handle unaligned start bytes (cnt = 0x%08lx)\n", cnt));
 456                data = 0;
 457                for (i=0, cp=wp; i<l; ++i, ++cp) {
 458                        data = (data << 8) | (*(uchar *)cp);
 459                }
 460                for (; i<BUFF_INC && cnt>0; ++i) {
 461                        data = (data << 8) | *src++;
 462                        --cnt;
 463                        ++cp;
 464                }
 465                for (; cnt==0 && i<BUFF_INC; ++i, ++cp) {
 466                        data = (data << 8) | (*(uchar *)cp);
 467                }
 468
 469                if ((rc = write_word(info, wp, data)) != 0) {
 470                        return (rc);
 471                }
 472                wp += BUFF_INC;
 473        }
 474
 475        /*
 476         * handle (half)word aligned part
 477         */
 478        mvdebug ((" handle word aligned part (cnt = 0x%08lx)\n", cnt));
 479        while (cnt >= BUFF_INC) {
 480                data = 0;
 481                for (i=0; i<BUFF_INC; ++i) {
 482                        data = (data << 8) | *src++;
 483                }
 484                if ((rc = write_word(info, wp, data)) != 0) {
 485                        return (rc);
 486                }
 487                wp  += BUFF_INC;
 488                cnt -= BUFF_INC;
 489        }
 490
 491        if (cnt == 0) {
 492                return (0);
 493        }
 494
 495        /*
 496         * handle unaligned tail bytes
 497         */
 498        mvdebug ((" handle unaligned tail bytes (cnt = 0x%08lx)\n", cnt));
 499        data = 0;
 500        for (i=0, cp=wp; i<BUFF_INC && cnt>0; ++i, ++cp) {
 501                data = (data << 8) | *src++;
 502                --cnt;
 503        }
 504        for (; i<BUFF_INC; ++i, ++cp) {
 505                data = (data << 8) | (*(uchar *)cp);
 506        }
 507
 508        return (write_word(info, wp, data));
 509}
 510
 511#if (FLASH_BUS_WIDTH >= 16)
 512        #define WRITE_ADDR1 0x0555
 513        #define WRITE_ADDR2 0x02AA
 514#else
 515        #define WRITE_ADDR1 0x0AAA
 516        #define WRITE_ADDR2 0x0555
 517        #define WRITE_ADDR3 WRITE_ADDR1
 518#endif
 519
 520#define WRITE_DATA1 (0x00AA00AA & FLASH_DATA_MASK)
 521#define WRITE_DATA2 (0x00550055 & FLASH_DATA_MASK)
 522#define WRITE_DATA3 (0x00A000A0 & FLASH_DATA_MASK)
 523
 524#define WRITE_CONFIRM_DATA ERASE_CONFIRM_DATA
 525
 526/*-----------------------------------------------------------------------
 527 * Write a byte to Flash, returns:
 528 * 0 - OK
 529 * 1 - write timeout
 530 * 2 - Flash not erased
 531 */
 532static int write_char (flash_info_t *info, ulong dest, uchar data)
 533{
 534        vu_char *addr = (vu_char *)(info->start[0]);
 535        ulong start;
 536        int flag;
 537
 538        /* Check if Flash is (sufficiently) erased */
 539        if ((*((vu_char *)dest) & data) != data) {
 540                printf(" *** ERROR: Flash not erased !\n");
 541                return (2);
 542        }
 543        flag = disable_interrupts();
 544
 545        addr[WRITE_ADDR1] = WRITE_DATA1;
 546        addr[WRITE_ADDR2] = WRITE_DATA2;
 547        addr[WRITE_ADDR3] = WRITE_DATA3;
 548        *((vu_char *)dest) = data;
 549
 550        if (flag)
 551                enable_interrupts();
 552
 553        /* data polling for D7 */
 554        start = get_timer (0);
 555        addr = (vu_char *)dest;
 556        while (( (*addr) & WRITE_CONFIRM_DATA) != (data & WRITE_CONFIRM_DATA)) {
 557                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 558                        printf(" *** ERROR: Flash write timeout !");
 559                        return (1);
 560                }
 561        }
 562        mvdebug (("-write_byte\n"));
 563        return (0);
 564}
 565
 566/*-----------------------------------------------------------------------
 567 * Write a word to Flash, returns:
 568 * 0 - OK
 569 * 1 - write timeout
 570 * 2 - Flash not erased
 571 */
 572static int write_word (flash_info_t *info, ulong dest, ulong data)
 573{
 574        int i,
 575                result = 0;
 576
 577        mvdebug (("+write_word : 0x%08lx @ 0x%08lx\n", data, dest));
 578        for ( i=0; (i < 4) && (result == 0); i++, dest+=1 )
 579                result = write_char (info, dest, (data >> (8*(3-i))) & 0xff );
 580        mvdebug (("-write_word\n"));
 581        return result;
 582}
 583/*---------------------------------------------------------------- */
 584