uboot/board/altera/common/flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000-2004
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24
  25#include <common.h>
  26#include <nios.h>
  27
  28flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
  29
  30/*--------------------------------------------------------------------*/
  31void flash_print_info (flash_info_t * info)
  32{
  33        int i, k;
  34        unsigned long size;
  35        int erased;
  36        volatile unsigned char *flash;
  37
  38        printf ("  Size: %ld KB in %d Sectors\n",
  39                info->size >> 10, info->sector_count);
  40        printf ("  Sector Start Addresses:");
  41        for (i = 0; i < info->sector_count; ++i) {
  42
  43                /* Check if whole sector is erased */
  44                if (i != (info->sector_count - 1))
  45                        size = info->start[i + 1] - info->start[i];
  46                else
  47                        size = info->start[0] + info->size - info->start[i];
  48                erased = 1;
  49                flash = (volatile unsigned char *) info->start[i];
  50                for (k = 0; k < size; k++) {
  51                        if (*flash++ != 0xff) {
  52                                erased = 0;
  53                                break;
  54                        }
  55                }
  56
  57                /* Print the info */
  58                if ((i % 5) == 0)
  59                        printf ("\n   ");
  60                printf (" %08lX%s%s", info->start[i], erased ? " E" : "  ",
  61                        info->protect[i] ? "RO " : "   ");
  62        }
  63        printf ("\n");
  64}
  65
  66/*-------------------------------------------------------------------*/
  67
  68
  69int flash_erase (flash_info_t * info, int s_first, int s_last)
  70{
  71        volatile CONFIG_SYS_FLASH_WORD_SIZE *addr = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
  72        volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2;
  73        int prot, sect;
  74        unsigned oldpri;
  75        ulong start;
  76
  77        /* Some sanity checking */
  78        if ((s_first < 0) || (s_first > s_last)) {
  79                printf ("- no sectors to erase\n");
  80                return 1;
  81        }
  82
  83        prot = 0;
  84        for (sect = s_first; sect <= s_last; ++sect) {
  85                if (info->protect[sect]) {
  86                        prot++;
  87                }
  88        }
  89        if (prot) {
  90                printf ("- Warning: %d protected sectors will not be erased!\n",
  91                        prot);
  92        } else {
  93                printf ("\n");
  94        }
  95
  96#ifdef DEBUG
  97        for (sect = s_first; sect <= s_last; sect++) {
  98                printf("- Erase: Sect: %i @ 0x%08x\n", sect,  info->start[sect]);
  99        }
 100#endif
 101
 102        /* NOTE: disabling interrupts on Nios can be very bad since it
 103         * also disables the LO_LIMIT exception. It's better here to
 104         * set the interrupt priority to 3 & restore it when we're done.
 105         */
 106        oldpri = ipri (3);
 107
 108        /* It's ok to erase multiple sectors provided we don't delay more
 109         * than 50 usec between cmds ... at which point the erase time-out
 110         * occurs. So don't go and put printf() calls in the loop ... it
 111         * won't be very helpful ;-)
 112         */
 113        for (sect = s_first; sect <= s_last; sect++) {
 114                if (info->protect[sect] == 0) { /* not protected */
 115                        addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
 116                        *addr = 0xaa;
 117                        *addr = 0x55;
 118                        *addr = 0x80;
 119                        *addr = 0xaa;
 120                        *addr = 0x55;
 121                        *addr2 = 0x30;
 122                        /* Now just wait for 0xff & provide some user
 123                         * feedback while we wait. Here we have to grant
 124                         * timer interrupts. Otherwise get_timer() can't
 125                         * work right. */
 126                        ipri(oldpri);
 127                        start = get_timer (0);
 128                        while (*addr2 != 0xff) {
 129                                udelay (1000 * 1000);
 130                                putc ('.');
 131                                if (get_timer (start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
 132                                        printf ("timeout\n");
 133                                        return 1;
 134                                }
 135                        }
 136                        oldpri = ipri (3); /* disallow non important irqs again */
 137                }
 138        }
 139
 140        printf ("\n");
 141
 142        /* Restore interrupt priority */
 143        ipri (oldpri);
 144
 145        return 0;
 146}
 147
 148/*-----------------------------------------------------------------------
 149 * Copy memory to flash, returns:
 150 * 0 - OK
 151 * 1 - write timeout
 152 * 2 - Flash not erased
 153 */
 154
 155int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 156{
 157
 158        vu_char *cmd = (vu_char *) info->start[0];
 159        vu_char *dst = (vu_char *) addr;
 160        unsigned char b;
 161        unsigned oldpri;
 162        ulong start;
 163
 164        while (cnt) {
 165                /* Check for sufficient erase */
 166                b = *src;
 167                if ((*dst & b) != b) {
 168                        printf ("%02x : %02x\n", *dst, b);
 169                        return (2);
 170                }
 171
 172                /* Disable interrupts other than window underflow
 173                 * (interrupt priority 2)
 174                 */
 175                oldpri = ipri (3);
 176                *cmd = 0xaa;
 177                *cmd = 0x55;
 178                *cmd = 0xa0;
 179                *dst = b;
 180
 181                /* Verify write */
 182                start = get_timer (0);
 183                while (*dst != b) {
 184                        if (get_timer (start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
 185                                ipri (oldpri);
 186                                return 1;
 187                        }
 188                }
 189                dst++;
 190                src++;
 191                cnt--;
 192                ipri (oldpri);
 193        }
 194
 195        return (0);
 196}
 197