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