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