uboot/board/cm41xx/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2005
   3 * Greg Ungerer, OpenGear Inc, greg.ungerer@opengear.com
   4 *
   5 * (C) Copyright 2001
   6 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
   7 *
   8 * (C) Copyright 2001
   9 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  10 *
  11 * See file CREDITS for list of people who contributed to this
  12 * project.
  13 *
  14 * This program is free software; you can redistribute it and/or
  15 * modify it under the terms of the GNU General Public License as
  16 * published by the Free Software Foundation; either version 2 of
  17 * the License, or (at your option) any later version.
  18 *
  19 * This program is distributed in the hope that it will be useful,
  20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22 * GNU General Public License for more details.
  23 *
  24 * You should have received a copy of the GNU General Public License
  25 * along with this program; if not, write to the Free Software
  26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  27 * MA 02111-1307 USA
  28 */
  29
  30#include <common.h>
  31#include <linux/byteorder/swab.h>
  32
  33
  34flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];    /* info for FLASH chips */
  35
  36#define mb() __asm__ __volatile__ ("" : : : "memory")
  37
  38/*-----------------------------------------------------------------------
  39 * Functions
  40 */
  41static ulong flash_get_size (unsigned char * addr, flash_info_t * info);
  42static int write_data (flash_info_t * info, ulong dest, unsigned char data);
  43static void flash_get_offsets (ulong base, flash_info_t * info);
  44void inline spin_wheel (void);
  45
  46/*-----------------------------------------------------------------------
  47 */
  48
  49unsigned long flash_init (void)
  50{
  51        int i;
  52        ulong size = 0;
  53
  54        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  55                switch (i) {
  56                case 0:
  57                        flash_get_size ((unsigned char *) PHYS_FLASH_1, &flash_info[i]);
  58                        flash_get_offsets (PHYS_FLASH_1, &flash_info[i]);
  59                        break;
  60                case 1:
  61                        /* ignore for now */
  62                        flash_info[i].flash_id = FLASH_UNKNOWN;
  63                        break;
  64                default:
  65                        panic ("configured too many flash banks!\n");
  66                        break;
  67                }
  68                size += flash_info[i].size;
  69        }
  70
  71        /* Protect monitor and environment sectors
  72         */
  73        flash_protect (FLAG_PROTECT_SET,
  74                       CONFIG_SYS_FLASH_BASE,
  75                       CONFIG_SYS_FLASH_BASE + _bss_start_ofs,
  76                       &flash_info[0]);
  77
  78        return size;
  79}
  80
  81/*-----------------------------------------------------------------------
  82 */
  83static void flash_get_offsets (ulong base, flash_info_t * info)
  84{
  85        int i;
  86
  87        if (info->flash_id == FLASH_UNKNOWN)
  88                return;
  89
  90        if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
  91                for (i = 0; i < info->sector_count; i++) {
  92                        info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE);
  93                        info->protect[i] = 0;
  94                }
  95        }
  96}
  97
  98/*-----------------------------------------------------------------------
  99 */
 100void flash_print_info (flash_info_t * info)
 101{
 102        int i;
 103
 104        if (info->flash_id == FLASH_UNKNOWN) {
 105                printf ("missing or unknown FLASH type\n");
 106                return;
 107        }
 108
 109        switch (info->flash_id & FLASH_VENDMASK) {
 110        case FLASH_MAN_INTEL:
 111                printf ("INTEL ");
 112                break;
 113        default:
 114                printf ("Unknown Vendor ");
 115                break;
 116        }
 117
 118        switch (info->flash_id & FLASH_TYPEMASK) {
 119        case FLASH_28F128J3A:
 120                printf ("28F128J3A\n");
 121                break;
 122        default:
 123                printf ("Unknown Chip Type\n");
 124                break;
 125        }
 126
 127        printf ("  Size: %ld MB in %d Sectors\n",
 128                info->size >> 20, info->sector_count);
 129
 130        printf ("  Sector Start Addresses:");
 131        for (i = 0; i < info->sector_count; ++i) {
 132                if ((i % 5) == 0)
 133                        printf ("\n   ");
 134                printf (" %08lX%s",
 135                        info->start[i], info->protect[i] ? " (RO)" : "     ");
 136        }
 137        printf ("\n");
 138        return;
 139}
 140
 141/*
 142 * The following code cannot be run from FLASH!
 143 */
 144static ulong flash_get_size (unsigned char * addr, flash_info_t * info)
 145{
 146        volatile unsigned char value;
 147
 148        /* Write auto select command: read Manufacturer ID */
 149        addr[0x5555] = 0xAA;
 150        addr[0x2AAA] = 0x55;
 151        addr[0x5555] = 0x90;
 152
 153        mb ();
 154        value = addr[0];
 155
 156        switch (value) {
 157
 158        case (unsigned char)INTEL_MANUFACT:
 159                info->flash_id = FLASH_MAN_INTEL;
 160                break;
 161
 162        default:
 163                info->flash_id = FLASH_UNKNOWN;
 164                info->sector_count = 0;
 165                info->size = 0;
 166                addr[0] = 0xFF; /* restore read mode */
 167                return (0);     /* no or unknown flash  */
 168        }
 169
 170        mb ();
 171        value = addr[2];        /* device ID            */
 172
 173        switch (value) {
 174
 175        case (unsigned char)INTEL_ID_28F640J3A:
 176                info->flash_id += FLASH_28F640J3A;
 177                info->sector_count = 64;
 178                info->size = 0x00800000;
 179                break;          /* => 8 MB     */
 180
 181        case (unsigned char)INTEL_ID_28F128J3A:
 182                info->flash_id += FLASH_28F128J3A;
 183                info->sector_count = 128;
 184                info->size = 0x01000000;
 185                break;          /* => 16 MB     */
 186
 187        default:
 188                info->flash_id = FLASH_UNKNOWN;
 189                break;
 190        }
 191
 192        if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
 193                printf ("** ERROR: sector count %d > max (%d) **\n",
 194                        info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
 195                info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
 196        }
 197
 198        addr[0] = 0xFF; /* restore read mode */
 199
 200        return (info->size);
 201}
 202
 203
 204/*-----------------------------------------------------------------------
 205 */
 206
 207int flash_erase (flash_info_t * info, int s_first, int s_last)
 208{
 209        int prot, sect;
 210        ulong type;
 211        int rcode = 0;
 212        ulong start;
 213
 214        if ((s_first < 0) || (s_first > s_last)) {
 215                if (info->flash_id == FLASH_UNKNOWN) {
 216                        printf ("- missing\n");
 217                } else {
 218                        printf ("- no sectors to erase\n");
 219                }
 220                return 1;
 221        }
 222
 223        type = (info->flash_id & FLASH_VENDMASK);
 224        if ((type != FLASH_MAN_INTEL)) {
 225                printf ("Can't erase unknown flash type %08lx - aborted\n",
 226                        info->flash_id);
 227                return 1;
 228        }
 229
 230        prot = 0;
 231        for (sect = s_first; sect <= s_last; ++sect) {
 232                if (info->protect[sect]) {
 233                        prot++;
 234                }
 235        }
 236
 237        if (prot)
 238                printf ("- Warning: %d protected sectors will not be erased!\n", prot);
 239        else
 240                printf ("\n");
 241
 242        /* Disable interrupts which might cause a timeout here */
 243        disable_interrupts();
 244
 245        /* Start erase on unprotected sectors */
 246        for (sect = s_first; sect <= s_last; sect++) {
 247                if (info->protect[sect] == 0) { /* not protected */
 248                        volatile unsigned char *addr;
 249                        unsigned char status;
 250
 251                        printf ("Erasing sector %2d ... ", sect);
 252
 253                        /* arm simple, non interrupt dependent timer */
 254                        start = get_timer(0);
 255
 256                        addr = (volatile unsigned char *) (info->start[sect]);
 257                        *addr = 0x50;   /* clear status register */
 258                        *addr = 0x20;   /* erase setup */
 259                        *addr = 0xD0;   /* erase confirm */
 260
 261                        while (((status = *addr) & 0x80) != 0x80) {
 262                                if (get_timer(start) >
 263                                    CONFIG_SYS_FLASH_ERASE_TOUT) {
 264                                        printf ("Timeout\n");
 265                                        *addr = 0xB0;   /* suspend erase */
 266                                        *addr = 0xFF;   /* reset to read mode */
 267                                        rcode = 1;
 268                                        break;
 269                                }
 270                        }
 271
 272                        *addr = 0x50;   /* clear status register cmd */
 273                        *addr = 0xFF;   /* resest to read mode */
 274
 275                        printf (" done\n");
 276                }
 277        }
 278        return rcode;
 279}
 280
 281/*-----------------------------------------------------------------------
 282 * Copy memory to flash, returns:
 283 * 0 - OK
 284 * 1 - write timeout
 285 * 2 - Flash not erased
 286 * 4 - Flash not identified
 287 */
 288
 289int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 290{
 291        ulong cp, wp;
 292        unsigned char data;
 293        int count, i, l, rc, port_width;
 294
 295        if (info->flash_id == FLASH_UNKNOWN)
 296                return 4;
 297
 298        wp = addr;
 299        port_width = 1;
 300
 301        /*
 302         * handle unaligned start bytes
 303         */
 304        if ((l = addr - wp) != 0) {
 305                data = 0;
 306                for (i = 0, cp = wp; i < l; ++i, ++cp) {
 307                        data = (data << 8) | (*(uchar *) cp);
 308                }
 309                for (; i < port_width && cnt > 0; ++i) {
 310                        data = (data << 8) | *src++;
 311                        --cnt;
 312                        ++cp;
 313                }
 314                for (; cnt == 0 && i < port_width; ++i, ++cp) {
 315                        data = (data << 8) | (*(uchar *) cp);
 316                }
 317
 318                if ((rc = write_data (info, wp, data)) != 0) {
 319                        return (rc);
 320                }
 321                wp += port_width;
 322        }
 323
 324        /*
 325         * handle word aligned part
 326         */
 327        count = 0;
 328        while (cnt >= port_width) {
 329                data = 0;
 330                for (i = 0; i < port_width; ++i) {
 331                        data = (data << 8) | *src++;
 332                }
 333                if ((rc = write_data (info, wp, data)) != 0) {
 334                        return (rc);
 335                }
 336                wp += port_width;
 337                cnt -= port_width;
 338                if (count++ > 0x800) {
 339                        spin_wheel ();
 340                        count = 0;
 341                }
 342        }
 343
 344        if (cnt == 0) {
 345                return (0);
 346        }
 347
 348        /*
 349         * handle unaligned tail bytes
 350         */
 351        data = 0;
 352        for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) {
 353                data = (data << 8) | *src++;
 354                --cnt;
 355        }
 356        for (; i < port_width; ++i, ++cp) {
 357                data = (data << 8) | (*(uchar *) cp);
 358        }
 359
 360        return (write_data (info, wp, data));
 361}
 362
 363/*-----------------------------------------------------------------------
 364 * Write a word or halfword to Flash, returns:
 365 * 0 - OK
 366 * 1 - write timeout
 367 * 2 - Flash not erased
 368 */
 369static int write_data (flash_info_t * info, ulong dest, unsigned char data)
 370{
 371        volatile unsigned char *addr = (volatile unsigned char *) dest;
 372        ulong status;
 373        ulong start;
 374
 375        /* Check if Flash is (sufficiently) erased */
 376        if ((*addr & data) != data) {
 377                printf ("not erased at %08lx (%lx)\n", (ulong) addr,
 378                        (ulong) * addr);
 379                return (2);
 380        }
 381        /* Disable interrupts which might cause a timeout here */
 382        disable_interrupts();
 383
 384        *addr = 0x40;   /* write setup */
 385        *addr = data;
 386
 387        /* arm simple, non interrupt dependent timer */
 388        start = get_timer(0);
 389
 390        /* wait while polling the status register */
 391        while (((status = *addr) & 0x80) != 0x80) {
 392                if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 393                        *addr = 0xFF;   /* restore read mode */
 394                        return (1);
 395                }
 396        }
 397
 398        *addr = 0xFF;   /* restore read mode */
 399
 400        return (0);
 401}
 402
 403void inline spin_wheel (void)
 404{
 405        static int p = 0;
 406        static char w[] = "\\/-";
 407
 408        printf ("\010%c", w[p]);
 409        (++p == 3) ? (p = 0) : 0;
 410}
 411