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