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);
  34void inline 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 j, k;
  60
  61        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
  62
  63                info->start[0] = base;
  64                for (k = 0, j = 0; j < CONFIG_SYS_SST_SECT; j++, k++) {
  65                        info->start[k + 1] = info->start[k] + CONFIG_SYS_SST_SECTSZ;
  66                        info->protect[k] = 0;
  67                }
  68        }
  69
  70        return ERR_OK;
  71}
  72
  73void flash_print_info(flash_info_t * info)
  74{
  75        int i;
  76
  77        switch (info->flash_id & FLASH_VENDMASK) {
  78        case FLASH_MAN_SST:
  79                printf("SST ");
  80                break;
  81        default:
  82                printf("Unknown Vendor ");
  83                break;
  84        }
  85
  86        switch (info->flash_id & FLASH_TYPEMASK) {
  87        case FLASH_SST6401B:
  88                printf("SST39VF6401B\n");
  89                break;
  90        default:
  91                printf("Unknown Chip Type\n");
  92                return;
  93        }
  94
  95        if (info->size > 0x100000) {
  96                int remainder;
  97
  98                printf("  Size: %ld", info->size >> 20);
  99
 100                remainder = (info->size % 0x100000);
 101                if (remainder) {
 102                        remainder >>= 10;
 103                        remainder = (int)((float)
 104                                          (((float)remainder / (float)1024) *
 105                                           10000));
 106                        printf(".%d ", remainder);
 107                }
 108
 109                printf("MB in %d Sectors\n", info->sector_count);
 110        } else
 111                printf("  Size: %ld KB in %d Sectors\n",
 112                       info->size >> 10, info->sector_count);
 113
 114        printf("  Sector Start Addresses:");
 115        for (i = 0; i < info->sector_count; ++i) {
 116                if ((i % 5) == 0)
 117                        printf("\n   ");
 118                printf(" %08lX%s",
 119                       info->start[i], info->protect[i] ? " (RO)" : "     ");
 120        }
 121        printf("\n");
 122}
 123
 124/*
 125 * The following code cannot be run from FLASH!
 126 */
 127ulong flash_get_size(FPWV * addr, flash_info_t * info)
 128{
 129        u16 value;
 130
 131        addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA; /* for Atmel, Intel ignores this */
 132        addr[FLASH_CYCLE2] = (FPWV) 0x00550055; /* for Atmel, Intel ignores this */
 133        addr[FLASH_CYCLE1] = (FPWV) 0x00900090; /* selects Intel or Atmel */
 134
 135        switch (addr[0] & 0xffff) {
 136        case (u8) SST_MANUFACT:
 137                info->flash_id = FLASH_MAN_SST;
 138                value = addr[1];
 139                break;
 140        default:
 141                printf("Unknown Flash\n");
 142                info->flash_id = FLASH_UNKNOWN;
 143                info->sector_count = 0;
 144                info->size = 0;
 145
 146                *addr = (FPW) 0x00F000F0;
 147                return (0);     /* no or unknown flash  */
 148        }
 149
 150        switch (value) {
 151        case (u16) SST_ID_xF6401B:
 152                info->flash_id += FLASH_SST6401B;
 153                break;
 154        default:
 155                info->flash_id = FLASH_UNKNOWN;
 156                break;
 157        }
 158
 159        info->sector_count = 0;
 160        info->size = 0;
 161        info->sector_count = CONFIG_SYS_SST_SECT;
 162        info->size = CONFIG_SYS_SST_SECT * CONFIG_SYS_SST_SECTSZ;
 163
 164        /* reset ID mode */
 165        *addr = (FPWV) 0x00F000F0;
 166
 167        if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
 168                printf("** ERROR: sector count %d > max (%d) **\n",
 169                       info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
 170                info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 171        }
 172
 173        return (info->size);
 174}
 175
 176int flash_erase(flash_info_t * info, int s_first, int s_last)
 177{
 178        FPWV *addr;
 179        int flag, prot, sect, count;
 180        ulong type, start, last;
 181        int rcode = 0, flashtype = 0;
 182
 183        if ((s_first < 0) || (s_first > s_last)) {
 184                if (info->flash_id == FLASH_UNKNOWN)
 185                        printf("- missing\n");
 186                else
 187                        printf("- no sectors to erase\n");
 188                return 1;
 189        }
 190
 191        type = (info->flash_id & FLASH_VENDMASK);
 192
 193        switch (type) {
 194        case FLASH_MAN_SST:
 195                flashtype = 1;
 196                break;
 197        default:
 198                type = (info->flash_id & FLASH_VENDMASK);
 199                printf("Can't erase unknown flash type %08lx - aborted\n",
 200                       info->flash_id);
 201                return 1;
 202        }
 203
 204        prot = 0;
 205        for (sect = s_first; sect <= s_last; ++sect) {
 206                if (info->protect[sect]) {
 207                        prot++;
 208                }
 209        }
 210
 211        if (prot)
 212                printf("- Warning: %d protected sectors will not be erased!\n",
 213                       prot);
 214        else
 215                printf("\n");
 216
 217        flag = disable_interrupts();
 218
 219        start = get_timer(0);
 220        last = start;
 221
 222        if ((s_last - s_first) == (CONFIG_SYS_SST_SECT - 1)) {
 223                if (prot == 0) {
 224                        addr = (FPWV *) info->start[0];
 225
 226                        addr[FLASH_CYCLE1] = 0x00AA;    /* unlock */
 227                        addr[FLASH_CYCLE2] = 0x0055;    /* unlock */
 228                        addr[FLASH_CYCLE1] = 0x0080;    /* erase mode */
 229                        addr[FLASH_CYCLE1] = 0x00AA;    /* unlock */
 230                        addr[FLASH_CYCLE2] = 0x0055;    /* unlock */
 231                        *addr = 0x0030; /* erase chip */
 232
 233                        count = 0;
 234                        start = get_timer(0);
 235
 236                        while ((*addr & 0x0080) != 0x0080) {
 237                                if (count++ > 0x10000) {
 238                                        spin_wheel();
 239                                        count = 0;
 240                                }
 241
 242                                if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 243                                        printf("Timeout\n");
 244                                        *addr = 0x00F0; /* reset to read mode */
 245
 246                                        return 1;
 247                                }
 248                        }
 249
 250                        *addr = 0x00F0; /* reset to read mode */
 251
 252                        printf("\b. done\n");
 253
 254                        if (flag)
 255                                enable_interrupts();
 256
 257                        return 0;
 258                } else if (prot == CONFIG_SYS_SST_SECT) {
 259                        return 1;
 260                }
 261        }
 262
 263        /* Start erase on unprotected sectors */
 264        for (sect = s_first; sect <= s_last; sect++) {
 265                if (info->protect[sect] == 0) { /* not protected */
 266
 267                        addr = (FPWV *) (info->start[sect]);
 268
 269                        printf(".");
 270
 271                        /* arm simple, non interrupt dependent timer */
 272                        start = get_timer(0);
 273
 274                        switch (flashtype) {
 275                        case 1:
 276                                {
 277                                        FPWV *base;     /* first address in bank */
 278
 279                                        flag = disable_interrupts();
 280
 281                                        base = (FPWV *) (CONFIG_SYS_FLASH_BASE);        /* First sector */
 282
 283                                        base[FLASH_CYCLE1] = 0x00AA;    /* unlock */
 284                                        base[FLASH_CYCLE2] = 0x0055;    /* unlock */
 285                                        base[FLASH_CYCLE1] = 0x0080;    /* erase mode */
 286                                        base[FLASH_CYCLE1] = 0x00AA;    /* unlock */
 287                                        base[FLASH_CYCLE2] = 0x0055;    /* unlock */
 288                                        *addr = 0x0050; /* erase sector */
 289
 290                                        if (flag)
 291                                                enable_interrupts();
 292
 293                                        while ((*addr & 0x0080) != 0x0080) {
 294                                                if (get_timer(start) >
 295                                                    CONFIG_SYS_FLASH_ERASE_TOUT) {
 296                                                        printf("Timeout\n");
 297                                                        *addr = 0x00F0; /* reset to read mode */
 298
 299                                                        rcode = 1;
 300                                                        break;
 301                                                }
 302                                        }
 303
 304                                        *addr = 0x00F0; /* reset to read mode */
 305                                        break;
 306                                }
 307                        }       /* switch (flashtype) */
 308                }
 309        }
 310        printf(" done\n");
 311
 312        if (flag)
 313                enable_interrupts();
 314
 315        return rcode;
 316}
 317
 318int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 319{
 320        ulong wp, count;
 321        u16 data;
 322        int rc, port_width;
 323
 324        if (info->flash_id == FLASH_UNKNOWN)
 325                return 4;
 326
 327        /* get lower word aligned address */
 328        wp = addr;
 329        port_width = sizeof(FPW);
 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
 442void inline 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