uboot/board/freescale/m5253demo/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000-2003
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
   6 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12
  13#include <asm/immap.h>
  14
  15#ifndef CONFIG_SYS_FLASH_CFI
  16typedef unsigned short FLASH_PORT_WIDTH;
  17typedef volatile unsigned short FLASH_PORT_WIDTHV;
  18
  19#define FPW             FLASH_PORT_WIDTH
  20#define FPWV            FLASH_PORT_WIDTHV
  21
  22#define FLASH_CYCLE1    0x5555
  23#define FLASH_CYCLE2    0x2aaa
  24
  25#define SYNC                    __asm__("nop")
  26
  27/*-----------------------------------------------------------------------
  28 * Functions
  29 */
  30
  31ulong flash_get_size(FPWV * addr, flash_info_t * info);
  32int flash_get_offsets(ulong base, flash_info_t * info);
  33int write_word(flash_info_t * info, FPWV * dest, u16 data);
  34static inline void spin_wheel(void);
  35
  36flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  37
  38ulong flash_init(void)
  39{
  40        ulong size = 0;
  41        ulong fbase = 0;
  42
  43        fbase = (ulong) CONFIG_SYS_FLASH_BASE;
  44        flash_get_size((FPWV *) fbase, &flash_info[0]);
  45        flash_get_offsets((ulong) fbase, &flash_info[0]);
  46        fbase += flash_info[0].size;
  47        size += flash_info[0].size;
  48
  49        /* Protect monitor and environment sectors */
  50        flash_protect(FLAG_PROTECT_SET,
  51                      CONFIG_SYS_MONITOR_BASE,
  52                      CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
  53
  54        return size;
  55}
  56
  57int flash_get_offsets(ulong base, flash_info_t * info)
  58{
  59        int i;
  60
  61        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
  62
  63                info->start[0] = base;
  64                info->protect[0] = 0;
  65                for (i = 1; i < CONFIG_SYS_SST_SECT; i++) {
  66                        info->start[i] = info->start[i - 1]
  67                                                + CONFIG_SYS_SST_SECTSZ;
  68                        info->protect[i] = 0;
  69                }
  70        }
  71
  72        return ERR_OK;
  73}
  74
  75void flash_print_info(flash_info_t * info)
  76{
  77        int i;
  78
  79        switch (info->flash_id & FLASH_VENDMASK) {
  80        case FLASH_MAN_SST:
  81                printf("SST ");
  82                break;
  83        default:
  84                printf("Unknown Vendor ");
  85                break;
  86        }
  87
  88        switch (info->flash_id & FLASH_TYPEMASK) {
  89        case FLASH_SST6401B:
  90                printf("SST39VF6401B\n");
  91                break;
  92        default:
  93                printf("Unknown Chip Type\n");
  94                return;
  95        }
  96
  97        if (info->size > 0x100000) {
  98                int remainder;
  99
 100                printf("  Size: %ld", info->size >> 20);
 101
 102                remainder = (info->size % 0x100000);
 103                if (remainder) {
 104                        remainder >>= 10;
 105                        remainder = (int)((float)
 106                                          (((float)remainder / (float)1024) *
 107                                           10000));
 108                        printf(".%d ", remainder);
 109                }
 110
 111                printf("MB in %d Sectors\n", info->sector_count);
 112        } else
 113                printf("  Size: %ld KB in %d Sectors\n",
 114                       info->size >> 10, info->sector_count);
 115
 116        printf("  Sector Start Addresses:");
 117        for (i = 0; i < info->sector_count; ++i) {
 118                if ((i % 5) == 0)
 119                        printf("\n   ");
 120                printf(" %08lX%s",
 121                       info->start[i], info->protect[i] ? " (RO)" : "     ");
 122        }
 123        printf("\n");
 124}
 125
 126/*
 127 * The following code cannot be run from FLASH!
 128 */
 129ulong flash_get_size(FPWV * addr, flash_info_t * info)
 130{
 131        u16 value;
 132
 133        addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA; /* for Atmel, Intel ignores this */
 134        addr[FLASH_CYCLE2] = (FPWV) 0x00550055; /* for Atmel, Intel ignores this */
 135        addr[FLASH_CYCLE1] = (FPWV) 0x00900090; /* selects Intel or Atmel */
 136
 137        switch (addr[0] & 0xffff) {
 138        case (u8) SST_MANUFACT:
 139                info->flash_id = FLASH_MAN_SST;
 140                value = addr[1];
 141                break;
 142        default:
 143                printf("Unknown Flash\n");
 144                info->flash_id = FLASH_UNKNOWN;
 145                info->sector_count = 0;
 146                info->size = 0;
 147
 148                *addr = (FPW) 0x00F000F0;
 149                return (0);     /* no or unknown flash  */
 150        }
 151
 152        switch (value) {
 153        case (u16) SST_ID_xF6401B:
 154                info->flash_id += FLASH_SST6401B;
 155                break;
 156        default:
 157                info->flash_id = FLASH_UNKNOWN;
 158                break;
 159        }
 160
 161        info->sector_count = 0;
 162        info->size = 0;
 163        info->sector_count = CONFIG_SYS_SST_SECT;
 164        info->size = CONFIG_SYS_SST_SECT * CONFIG_SYS_SST_SECTSZ;
 165
 166        /* reset ID mode */
 167        *addr = (FPWV) 0x00F000F0;
 168
 169        if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
 170                printf("** ERROR: sector count %d > max (%d) **\n",
 171                       info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
 172                info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 173        }
 174
 175        return (info->size);
 176}
 177
 178int flash_erase(flash_info_t * info, int s_first, int s_last)
 179{
 180        FPWV *addr;
 181        int flag, prot, sect, count;
 182        ulong type, start;
 183        int rcode = 0, flashtype = 0;
 184
 185        if ((s_first < 0) || (s_first > s_last)) {
 186                if (info->flash_id == FLASH_UNKNOWN)
 187                        printf("- missing\n");
 188                else
 189                        printf("- no sectors to erase\n");
 190                return 1;
 191        }
 192
 193        type = (info->flash_id & FLASH_VENDMASK);
 194
 195        switch (type) {
 196        case FLASH_MAN_SST:
 197                flashtype = 1;
 198                break;
 199        default:
 200                type = (info->flash_id & FLASH_VENDMASK);
 201                printf("Can't erase unknown flash type %08lx - aborted\n",
 202                       info->flash_id);
 203                return 1;
 204        }
 205
 206        prot = 0;
 207        for (sect = s_first; sect <= s_last; ++sect) {
 208                if (info->protect[sect]) {
 209                        prot++;
 210                }
 211        }
 212
 213        if (prot)
 214                printf("- Warning: %d protected sectors will not be erased!\n",
 215                       prot);
 216        else
 217                printf("\n");
 218
 219        flag = disable_interrupts();
 220
 221        start = get_timer(0);
 222
 223        if ((s_last - s_first) == (CONFIG_SYS_SST_SECT - 1)) {
 224                if (prot == 0) {
 225                        addr = (FPWV *) info->start[0];
 226
 227                        addr[FLASH_CYCLE1] = 0x00AA;    /* unlock */
 228                        addr[FLASH_CYCLE2] = 0x0055;    /* unlock */
 229                        addr[FLASH_CYCLE1] = 0x0080;    /* erase mode */
 230                        addr[FLASH_CYCLE1] = 0x00AA;    /* unlock */
 231                        addr[FLASH_CYCLE2] = 0x0055;    /* unlock */
 232                        *addr = 0x0030; /* erase chip */
 233
 234                        count = 0;
 235                        start = get_timer(0);
 236
 237                        while ((*addr & 0x0080) != 0x0080) {
 238                                if (count++ > 0x10000) {
 239                                        spin_wheel();
 240                                        count = 0;
 241                                }
 242
 243                                if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 244                                        printf("Timeout\n");
 245                                        *addr = 0x00F0; /* reset to read mode */
 246
 247                                        return 1;
 248                                }
 249                        }
 250
 251                        *addr = 0x00F0; /* reset to read mode */
 252
 253                        printf("\b. done\n");
 254
 255                        if (flag)
 256                                enable_interrupts();
 257
 258                        return 0;
 259                } else if (prot == CONFIG_SYS_SST_SECT) {
 260                        return 1;
 261                }
 262        }
 263
 264        /* Start erase on unprotected sectors */
 265        for (sect = s_first; sect <= s_last; sect++) {
 266                if (info->protect[sect] == 0) { /* not protected */
 267
 268                        addr = (FPWV *) (info->start[sect]);
 269
 270                        printf(".");
 271
 272                        /* arm simple, non interrupt dependent timer */
 273                        start = get_timer(0);
 274
 275                        switch (flashtype) {
 276                        case 1:
 277                                {
 278                                        FPWV *base;     /* first address in bank */
 279
 280                                        flag = disable_interrupts();
 281
 282                                        base = (FPWV *) (CONFIG_SYS_FLASH_BASE);        /* First sector */
 283
 284                                        base[FLASH_CYCLE1] = 0x00AA;    /* unlock */
 285                                        base[FLASH_CYCLE2] = 0x0055;    /* unlock */
 286                                        base[FLASH_CYCLE1] = 0x0080;    /* erase mode */
 287                                        base[FLASH_CYCLE1] = 0x00AA;    /* unlock */
 288                                        base[FLASH_CYCLE2] = 0x0055;    /* unlock */
 289                                        *addr = 0x0050; /* erase sector */
 290
 291                                        if (flag)
 292                                                enable_interrupts();
 293
 294                                        while ((*addr & 0x0080) != 0x0080) {
 295                                                if (get_timer(start) >
 296                                                    CONFIG_SYS_FLASH_ERASE_TOUT) {
 297                                                        printf("Timeout\n");
 298                                                        *addr = 0x00F0; /* reset to read mode */
 299
 300                                                        rcode = 1;
 301                                                        break;
 302                                                }
 303                                        }
 304
 305                                        *addr = 0x00F0; /* reset to read mode */
 306                                        break;
 307                                }
 308                        }       /* switch (flashtype) */
 309                }
 310        }
 311        printf(" done\n");
 312
 313        if (flag)
 314                enable_interrupts();
 315
 316        return rcode;
 317}
 318
 319int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 320{
 321        ulong wp, count;
 322        u16 data;
 323        int rc;
 324
 325        if (info->flash_id == FLASH_UNKNOWN)
 326                return 4;
 327
 328        /* get lower word aligned address */
 329        wp = addr;
 330
 331        /* handle unaligned start bytes */
 332        if (wp & 1) {
 333                data = *((FPWV *) wp);
 334                data = (data << 8) | *src;
 335
 336                if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
 337                        return (rc);
 338
 339                wp++;
 340                cnt -= 1;
 341                src++;
 342        }
 343
 344        while (cnt >= 2) {
 345                /*
 346                 * handle word aligned part
 347                 */
 348                count = 0;
 349                data = *((FPWV *) src);
 350
 351                if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
 352                        return (rc);
 353
 354                wp += 2;
 355                src += 2;
 356                cnt -= 2;
 357
 358                if (count++ > 0x800) {
 359                        spin_wheel();
 360                        count = 0;
 361                }
 362        }
 363        /* handle word aligned part */
 364        if (cnt) {
 365                /* handle word aligned part */
 366                count = 0;
 367                data = *((FPWV *) wp);
 368
 369                data = (data & 0x00FF) | (*src << 8);
 370
 371                if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
 372                        return (rc);
 373
 374                wp++;
 375                src++;
 376                cnt -= 1;
 377                if (count++ > 0x800) {
 378                        spin_wheel();
 379                        count = 0;
 380                }
 381        }
 382
 383        if (cnt == 0)
 384                return ERR_OK;
 385
 386        return ERR_OK;
 387}
 388
 389/*-----------------------------------------------------------------------
 390 * Write a word to Flash
 391 * A word is 16 bits, whichever the bus width of the flash bank
 392 * (not an individual chip) is.
 393 *
 394 * returns:
 395 * 0 - OK
 396 * 1 - write timeout
 397 * 2 - Flash not erased
 398 */
 399int write_word(flash_info_t * info, FPWV * dest, u16 data)
 400{
 401        ulong start;
 402        int flag;
 403        int res = 0;            /* result, assume success */
 404        FPWV *base;             /* first address in flash bank */
 405
 406        /* Check if Flash is (sufficiently) erased */
 407        if ((*dest & (u8) data) != (u8) data) {
 408                return (2);
 409        }
 410
 411        base = (FPWV *) (CONFIG_SYS_FLASH_BASE);
 412
 413        /* Disable interrupts which might cause a timeout here */
 414        flag = disable_interrupts();
 415
 416        base[FLASH_CYCLE1] = (u8) 0x00AA00AA;   /* unlock */
 417        base[FLASH_CYCLE2] = (u8) 0x00550055;   /* unlock */
 418        base[FLASH_CYCLE1] = (u8) 0x00A000A0;   /* selects program mode */
 419
 420        *dest = data;           /* start programming the data */
 421
 422        /* re-enable interrupts if necessary */
 423        if (flag)
 424                enable_interrupts();
 425
 426        start = get_timer(0);
 427
 428        /* data polling for D7 */
 429        while (res == 0
 430               && (*dest & (u8) 0x00800080) != (data & (u8) 0x00800080)) {
 431                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 432                        *dest = (u8) 0x00F000F0;        /* reset bank */
 433                        res = 1;
 434                }
 435        }
 436
 437        *dest++ = (u8) 0x00F000F0;      /* reset bank */
 438
 439        return (res);
 440}
 441
 442static inline void spin_wheel(void)
 443{
 444        static int p = 0;
 445        static char w[] = "\\/-";
 446
 447        printf("\010%c", w[p]);
 448        (++p == 3) ? (p = 0) : 0;
 449}
 450
 451#endif
 452