uboot/board/csb226/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
   4 *
   5 * (C) Copyright 2002
   6 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   7 * Marius Groeger <mgroeger@sysgo.de>
   8 *
   9 * (C) Copyright 2002
  10 * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>
  11 *
  12 * (C) Copyright 2003 (2 x 16 bit Flash bank patches)
  13 * Rolf Peukert, IMMS gGmbH, <rolf.peukert@imms.de>
  14 *
  15 * See file CREDITS for list of people who contributed to this
  16 * project.
  17 *
  18 * This program is free software; you can redistribute it and/or
  19 * modify it under the terms of the GNU General Public License as
  20 * published by the Free Software Foundation; either version 2 of
  21 * the License, or (at your option) any later version.
  22 *
  23 * This program is distributed in the hope that it will be useful,
  24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26 * GNU General Public License for more details.
  27 *
  28 * You should have received a copy of the GNU General Public License
  29 * along with this program; if not, write to the Free Software
  30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  31 * MA 02111-1307 USA
  32 */
  33
  34#include <common.h>
  35#include <asm/arch/pxa-regs.h>
  36
  37#define FLASH_BANK_SIZE 0x02000000
  38#define MAIN_SECT_SIZE  0x40000         /* 2x16 = 256k per sector */
  39
  40flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  41
  42
  43/**
  44 * flash_init: - initialize data structures for flash chips
  45 *
  46 * @return: size of the flash
  47 */
  48
  49ulong flash_init(void)
  50{
  51        int i, j;
  52        ulong size = 0;
  53
  54        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
  55                ulong flashbase = 0;
  56                flash_info[i].flash_id =
  57                        (INTEL_MANUFACT & FLASH_VENDMASK) |
  58                        (INTEL_ID_28F128J3 & FLASH_TYPEMASK);
  59                flash_info[i].size = FLASH_BANK_SIZE;
  60                flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
  61                memset(flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
  62
  63                switch (i) {
  64                case 0:
  65                        flashbase = PHYS_FLASH_1;
  66                        break;
  67                default:
  68                        panic("configured too many flash banks!\n");
  69                        break;
  70                }
  71                for (j = 0; j < flash_info[i].sector_count; j++) {
  72                        flash_info[i].start[j] = flashbase + j*MAIN_SECT_SIZE;
  73                }
  74                size += flash_info[i].size;
  75        }
  76
  77        /* Protect monitor and environment sectors */
  78        flash_protect(FLAG_PROTECT_SET,
  79                        CONFIG_SYS_FLASH_BASE,
  80                        CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
  81                        &flash_info[0]);
  82
  83        flash_protect(FLAG_PROTECT_SET,
  84                        CONFIG_ENV_ADDR,
  85                        CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
  86                        &flash_info[0]);
  87
  88        return size;
  89}
  90
  91
  92/**
  93 * flash_print_info: - print information about the flash situation
  94 */
  95
  96void flash_print_info  (flash_info_t *info)
  97{
  98        int i, j;
  99
 100        for (j=0; j<CONFIG_SYS_MAX_FLASH_BANKS; j++) {
 101
 102                switch (info->flash_id & FLASH_VENDMASK) {
 103                case (INTEL_MANUFACT & FLASH_VENDMASK):
 104                        printf ("Intel: ");
 105                        break;
 106                default:
 107                        printf ("Unknown Vendor ");
 108                        break;
 109                }
 110
 111                switch (info->flash_id & FLASH_TYPEMASK) {
 112                case (INTEL_ID_28F128J3 & FLASH_TYPEMASK):
 113                        printf("28F128J3 (128Mbit)\n");
 114                        break;
 115                default:
 116                        printf("Unknown Chip Type\n");
 117                        return;
 118                }
 119
 120                printf("  Size: %ld MB in %d Sectors\n",
 121                        info->size >> 20, info->sector_count);
 122
 123                printf("  Sector Start Addresses:");
 124                for (i = 0; i < info->sector_count; i++) {
 125                        if ((i % 5) == 0) printf ("\n   ");
 126
 127                        printf (" %08lX%s", info->start[i],
 128                                info->protect[i] ? " (RO)" : "     ");
 129                }
 130                printf ("\n");
 131                info++;
 132        }
 133}
 134
 135
 136/**
 137 * flash_erase: - erase flash sectors
 138 */
 139
 140int flash_erase(flash_info_t *info, int s_first, int s_last)
 141{
 142        int flag, prot, sect;
 143        int rc = ERR_OK;
 144
 145        if (info->flash_id == FLASH_UNKNOWN)
 146                return ERR_UNKNOWN_FLASH_TYPE;
 147
 148        if ((s_first < 0) || (s_first > s_last)) {
 149                return ERR_INVAL;
 150        }
 151
 152        if ((info->flash_id & FLASH_VENDMASK) != (INTEL_MANUFACT & FLASH_VENDMASK))
 153                return ERR_UNKNOWN_FLASH_VENDOR;
 154
 155        prot = 0;
 156        for (sect=s_first; sect<=s_last; ++sect) {
 157                if (info->protect[sect]) prot++;
 158        }
 159
 160        if (prot) return ERR_PROTECTED;
 161
 162        /*
 163         * Disable interrupts which might cause a timeout
 164         * here. Remember that our exception vectors are
 165         * at address 0 in the flash, and we don't want a
 166         * (ticker) exception to happen while the flash
 167         * chip is in programming mode.
 168         */
 169
 170        flag = disable_interrupts();
 171
 172        /* Start erase on unprotected sectors */
 173        for (sect = s_first; sect<=s_last && !ctrlc(); sect++) {
 174
 175                printf("Erasing sector %2d ... ", sect);
 176
 177                /* arm simple, non interrupt dependent timer */
 178                reset_timer_masked();
 179
 180                if (info->protect[sect] == 0) { /* not protected */
 181                        u32 * volatile addr = (u32 * volatile)(info->start[sect]);
 182
 183                        /* erase sector:                                    */
 184                        /* The strata flashs are aligned side by side on    */
 185                        /* the data bus, so we have to write the commands   */
 186                        /* to both chips here:                              */
 187
 188                        *addr = 0x00200020;     /* erase setup */
 189                        *addr = 0x00D000D0;     /* erase confirm */
 190
 191                        while ((*addr & 0x00800080) != 0x00800080) {
 192                                if (get_timer_masked() > CONFIG_SYS_FLASH_ERASE_TOUT) {
 193                                        *addr = 0x00B000B0; /* suspend erase*/
 194                                        *addr = 0x00FF00FF; /* read mode    */
 195                                        rc = ERR_TIMOUT;
 196                                        goto outahere;
 197                                }
 198                        }
 199                        *addr = 0x00500050; /* clear status register cmd.   */
 200                        *addr = 0x00FF00FF; /* reset to read mode           */
 201                }
 202                printf("ok.\n");
 203        }
 204        if (ctrlc()) printf("User Interrupt!\n");
 205
 206outahere:
 207        /* allow flash to settle - wait 10 ms */
 208        udelay_masked(10000);
 209
 210        if (flag) enable_interrupts();
 211
 212        return rc;
 213}
 214
 215/**
 216 * write_long: - copy memory to flash, assume a bank of 2 devices with 16bit each
 217 */
 218
 219static int write_long (flash_info_t *info, ulong dest, ulong data)
 220{
 221        u32 * volatile addr = (u32 * volatile)dest, val;
 222        int rc = ERR_OK;
 223        int flag;
 224
 225        /* read array command - just for the case... */
 226        *addr = 0x00FF00FF;
 227
 228        /* Check if Flash is (sufficiently) erased */
 229        if ((*addr & data) != data) return ERR_NOT_ERASED;
 230
 231        /*
 232         * Disable interrupts which might cause a timeout
 233         * here. Remember that our exception vectors are
 234         * at address 0 in the flash, and we don't want a
 235         * (ticker) exception to happen while the flash
 236         * chip is in programming mode.
 237         */
 238        flag = disable_interrupts();
 239
 240        /* clear status register command */
 241        *addr = 0x00500050;
 242
 243        /* program set-up command */
 244        *addr = 0x00400040;
 245
 246        /* latch address/data */
 247        *addr = data;
 248
 249        /* arm simple, non interrupt dependent timer */
 250        reset_timer_masked();
 251
 252        /* wait while polling the status register */
 253        while(((val = *addr) & 0x00800080) != 0x00800080) {
 254                if (get_timer_masked() > CONFIG_SYS_FLASH_WRITE_TOUT) {
 255                        rc = ERR_TIMOUT;
 256                        /* suspend program command */
 257                        *addr = 0x00B000B0;
 258                        goto outahere;
 259                }
 260        }
 261
 262        /* check for errors */
 263        if(val & 0x001A001A) {
 264                printf("\nFlash write error %02x at address %08lx\n",
 265                        (int)val, (unsigned long)dest);
 266                if(val & 0x00080008) {
 267                        printf("Voltage range error.\n");
 268                        rc = ERR_PROG_ERROR;
 269                        goto outahere;
 270                }
 271                if(val & 0x00020002) {
 272                        printf("Device protect error.\n");
 273                        rc = ERR_PROTECTED;
 274                        goto outahere;
 275                }
 276                if(val & 0x00100010) {
 277                        printf("Programming error.\n");
 278                        rc = ERR_PROG_ERROR;
 279                        goto outahere;
 280                }
 281                rc = ERR_PROG_ERROR;
 282                goto outahere;
 283        }
 284
 285outahere:
 286        /* read array command */
 287        *addr = 0x00FF00FF;
 288        if (flag) enable_interrupts();
 289
 290        return rc;
 291}
 292
 293
 294/**
 295 * write_buf: - Copy memory to flash.
 296 *
 297 * @param info:
 298 * @param src:  source of copy transaction
 299 * @param addr: where to copy to
 300 * @param cnt:  number of bytes to copy
 301 *
 302 * @return      error code
 303 */
 304
 305/* "long" version, uses 32bit words */
 306int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
 307{
 308        ulong cp, wp;
 309        ulong data;
 310        int l;
 311        int i, rc;
 312
 313        wp = (addr & ~3);       /* get lower word aligned address */
 314
 315        /*
 316         * handle unaligned start bytes
 317         */
 318        if ((l = addr - wp) != 0) {
 319                data = 0;
 320                for (i=0, cp=wp; i<l; ++i, ++cp) {
 321                        data = (data >> 8) | (*(uchar *)cp << 24);
 322                }
 323                for (; i<4 && cnt>0; ++i) {
 324                        data = (data >> 8) | (*src++ << 24);
 325                        --cnt;
 326                        ++cp;
 327                }
 328                for (; cnt==0 && i<4; ++i, ++cp) {
 329                        data = (data >> 8) | (*(uchar *)cp << 24);
 330                }
 331
 332                if ((rc = write_long(info, wp, data)) != 0) {
 333                        return (rc);
 334                }
 335                wp += 4;
 336        }
 337
 338        /*
 339         * handle word aligned part
 340         */
 341        while (cnt >= 4) {
 342                data = *((ulong*)src);
 343                if ((rc = write_long(info, wp, data)) != 0) {
 344                        return (rc);
 345                }
 346                src += 4;
 347                wp  += 4;
 348                cnt -= 4;
 349        }
 350
 351        if (cnt == 0) return ERR_OK;
 352
 353        /*
 354         * handle unaligned tail bytes
 355         */
 356        data = 0;
 357        for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
 358                data = (data >> 8) | (*src++ << 24);
 359                --cnt;
 360        }
 361        for (; i<4; ++i, ++cp) {
 362                data = (data >> 8) | (*(uchar *)cp << 24);
 363        }
 364
 365        return write_long(info, wp, data);
 366}
 367