uboot/common/flash.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2000
   4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   5 */
   6
   7/* #define DEBUG */
   8
   9#include <common.h>
  10#include <flash.h>
  11
  12#include <mtd/cfi_flash.h>
  13
  14extern flash_info_t  flash_info[]; /* info for FLASH chips */
  15
  16/*-----------------------------------------------------------------------
  17 * Functions
  18 */
  19
  20/*-----------------------------------------------------------------------
  21 * Set protection status for monitor sectors
  22 *
  23 * The monitor is always located in the _first_ Flash bank.
  24 * If necessary you have to map the second bank at lower addresses.
  25 */
  26void
  27flash_protect (int flag, ulong from, ulong to, flash_info_t *info)
  28{
  29        ulong b_end;
  30        short s_end;
  31        int i;
  32
  33        /* Do nothing if input data is bad. */
  34        if (!info || info->sector_count == 0 || info->size == 0 || to < from) {
  35                return;
  36        }
  37
  38        s_end = info->sector_count - 1; /* index of last sector */
  39        b_end = info->start[0] + info->size - 1;        /* bank end address */
  40
  41        debug ("flash_protect %s: from 0x%08lX to 0x%08lX\n",
  42                (flag & FLAG_PROTECT_SET) ? "ON" :
  43                        (flag & FLAG_PROTECT_CLEAR) ? "OFF" : "???",
  44                from, to);
  45
  46        /* There is nothing to do if we have no data about the flash
  47         * or the protect range and flash range don't overlap.
  48         */
  49        if (info->flash_id == FLASH_UNKNOWN ||
  50            to < info->start[0] || from > b_end) {
  51                return;
  52        }
  53
  54        for (i=0; i<info->sector_count; ++i) {
  55                ulong end;              /* last address in current sect */
  56
  57                end = (i == s_end) ? b_end : info->start[i + 1] - 1;
  58
  59                /* Update protection if any part of the sector
  60                 * is in the specified range.
  61                 */
  62                if (from <= end && to >= info->start[i]) {
  63                        if (flag & FLAG_PROTECT_CLEAR) {
  64#if defined(CONFIG_SYS_FLASH_PROTECTION)
  65                                flash_real_protect(info, i, 0);
  66#else
  67                                info->protect[i] = 0;
  68#endif  /* CONFIG_SYS_FLASH_PROTECTION */
  69                                debug ("protect off %d\n", i);
  70                        }
  71                        else if (flag & FLAG_PROTECT_SET) {
  72#if defined(CONFIG_SYS_FLASH_PROTECTION)
  73                                flash_real_protect(info, i, 1);
  74#else
  75                                info->protect[i] = 1;
  76#endif  /* CONFIG_SYS_FLASH_PROTECTION */
  77                                debug ("protect on %d\n", i);
  78                        }
  79                }
  80        }
  81}
  82
  83/*-----------------------------------------------------------------------
  84 */
  85
  86flash_info_t *
  87addr2info (ulong addr)
  88{
  89        flash_info_t *info;
  90        int i;
  91
  92        for (i=0, info = &flash_info[0]; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) {
  93                if (info->flash_id != FLASH_UNKNOWN &&
  94                    addr >= info->start[0] &&
  95                    /* WARNING - The '- 1' is needed if the flash
  96                     * is at the end of the address space, since
  97                     * info->start[0] + info->size wraps back to 0.
  98                     * Please don't change this unless you understand this.
  99                     */
 100                    addr <= info->start[0] + info->size - 1) {
 101                        return (info);
 102                }
 103        }
 104
 105        return (NULL);
 106}
 107
 108/*-----------------------------------------------------------------------
 109 * Copy memory to flash.
 110 * Make sure all target addresses are within Flash bounds,
 111 * and no protected sectors are hit.
 112 * Returns:
 113 * ERR_OK          0 - OK
 114 * ERR_TIMEOUT     1 - write timeout
 115 * ERR_NOT_ERASED  2 - Flash not erased
 116 * ERR_PROTECTED   4 - target range includes protected sectors
 117 * ERR_INVAL       8 - target address not in Flash memory
 118 * ERR_ALIGN       16 - target address not aligned on boundary
 119 *                      (only some targets require alignment)
 120 */
 121int
 122flash_write (char *src, ulong addr, ulong cnt)
 123{
 124        int i;
 125        ulong         end        = addr + cnt - 1;
 126        flash_info_t *info_first = addr2info (addr);
 127        flash_info_t *info_last  = addr2info (end );
 128        flash_info_t *info;
 129        __maybe_unused char *src_orig = src;
 130        __maybe_unused char *addr_orig = (char *)addr;
 131        __maybe_unused ulong cnt_orig = cnt;
 132
 133        if (cnt == 0) {
 134                return (ERR_OK);
 135        }
 136
 137        if (!info_first || !info_last) {
 138                return (ERR_INVAL);
 139        }
 140
 141        for (info = info_first; info <= info_last; ++info) {
 142                ulong b_end = info->start[0] + info->size;      /* bank end addr */
 143                short s_end = info->sector_count - 1;
 144                for (i=0; i<info->sector_count; ++i) {
 145                        ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];
 146
 147                        if ((end >= info->start[i]) && (addr < e_addr) &&
 148                            (info->protect[i] != 0) ) {
 149                                return (ERR_PROTECTED);
 150                        }
 151                }
 152        }
 153
 154        /* finally write data to flash */
 155        for (info = info_first; info <= info_last && cnt>0; ++info) {
 156                ulong len;
 157
 158                len = info->start[0] + info->size - addr;
 159                if (len > cnt)
 160                        len = cnt;
 161                if ((i = write_buff(info, (uchar *)src, addr, len)) != 0) {
 162                        return (i);
 163                }
 164                cnt  -= len;
 165                addr += len;
 166                src  += len;
 167        }
 168
 169#if defined(CONFIG_FLASH_VERIFY)
 170        if (memcmp(src_orig, addr_orig, cnt_orig)) {
 171                printf("\nVerify failed!\n");
 172                return ERR_PROG_ERROR;
 173        }
 174#endif /* CONFIG_SYS_FLASH_VERIFY_AFTER_WRITE */
 175
 176        return (ERR_OK);
 177}
 178
 179/*-----------------------------------------------------------------------
 180 */
 181
 182void flash_perror (int err)
 183{
 184        switch (err) {
 185        case ERR_OK:
 186                break;
 187        case ERR_TIMEOUT:
 188                puts ("Timeout writing to Flash\n");
 189                break;
 190        case ERR_NOT_ERASED:
 191                puts ("Flash not Erased\n");
 192                break;
 193        case ERR_PROTECTED:
 194                puts ("Can't write to protected Flash sectors\n");
 195                break;
 196        case ERR_INVAL:
 197                puts ("Outside available Flash\n");
 198                break;
 199        case ERR_ALIGN:
 200                puts ("Start and/or end address not on sector boundary\n");
 201                break;
 202        case ERR_UNKNOWN_FLASH_VENDOR:
 203                puts ("Unknown Vendor of Flash\n");
 204                break;
 205        case ERR_UNKNOWN_FLASH_TYPE:
 206                puts ("Unknown Type of Flash\n");
 207                break;
 208        case ERR_PROG_ERROR:
 209                puts ("General Flash Programming Error\n");
 210                break;
 211        case ERR_ABORTED:
 212                puts("Flash Programming Aborted\n");
 213                break;
 214        default:
 215                printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
 216                break;
 217        }
 218}
 219