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 flash_info_t *info; 92 int i; 93 94 for (i=0, info = &flash_info[0]; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) { 95 if (info->flash_id != FLASH_UNKNOWN && 96 addr >= info->start[0] && 97 /* WARNING - The '- 1' is needed if the flash 98 * is at the end of the address space, since 99 * info->start[0] + info->size wraps back to 0. 100 * Please don't change this unless you understand this. 101 */ 102 addr <= info->start[0] + info->size - 1) { 103 return (info); 104 } 105 } 106 107 return (NULL); 108 } 109 110 /*----------------------------------------------------------------------- 111 * Copy memory to flash. 112 * Make sure all target addresses are within Flash bounds, 113 * and no protected sectors are hit. 114 * Returns: 115 * ERR_OK 0 - OK 116 * ERR_TIMOUT 1 - write timeout 117 * ERR_NOT_ERASED 2 - Flash not erased 118 * ERR_PROTECTED 4 - target range includes protected sectors 119 * ERR_INVAL 8 - target address not in Flash memory 120 * ERR_ALIGN 16 - target address not aligned on boundary 121 * (only some targets require alignment) 122 */ 123 int 124 flash_write (char *src, ulong addr, ulong cnt) 125 { 126 int i; 127 ulong end = addr + cnt - 1; 128 flash_info_t *info_first = addr2info (addr); 129 flash_info_t *info_last = addr2info (end ); 130 flash_info_t *info; 131 __maybe_unused char *src_orig = src; 132 __maybe_unused char *addr_orig = (char *)addr; 133 __maybe_unused ulong cnt_orig = cnt; 134 135 if (cnt == 0) { 136 return (ERR_OK); 137 } 138 139 if (!info_first || !info_last) { 140 return (ERR_INVAL); 141 } 142 143 for (info = info_first; info <= info_last; ++info) { 144 ulong b_end = info->start[0] + info->size; /* bank end addr */ 145 short s_end = info->sector_count - 1; 146 for (i=0; i<info->sector_count; ++i) { 147 ulong e_addr = (i == s_end) ? b_end : info->start[i + 1]; 148 149 if ((end >= info->start[i]) && (addr < e_addr) && 150 (info->protect[i] != 0) ) { 151 return (ERR_PROTECTED); 152 } 153 } 154 } 155 156 /* finally write data to flash */ 157 for (info = info_first; info <= info_last && cnt>0; ++info) { 158 ulong len; 159 160 len = info->start[0] + info->size - addr; 161 if (len > cnt) 162 len = cnt; 163 if ((i = write_buff(info, (uchar *)src, addr, len)) != 0) { 164 return (i); 165 } 166 cnt -= len; 167 addr += len; 168 src += len; 169 } 170 171 #if defined(CONFIG_FLASH_VERIFY) 172 if (memcmp(src_orig, addr_orig, cnt_orig)) { 173 printf("\nVerify failed!\n"); 174 return ERR_PROG_ERROR; 175 } 176 #endif /* CONFIG_SYS_FLASH_VERIFY_AFTER_WRITE */ 177 178 return (ERR_OK); 179 } 180 181 /*----------------------------------------------------------------------- 182 */ 183 184 void flash_perror (int err) 185 { 186 switch (err) { 187 case ERR_OK: 188 break; 189 case ERR_TIMOUT: 190 puts ("Timeout writing to Flash\n"); 191 break; 192 case ERR_NOT_ERASED: 193 puts ("Flash not Erased\n"); 194 break; 195 case ERR_PROTECTED: 196 puts ("Can't write to protected Flash sectors\n"); 197 break; 198 case ERR_INVAL: 199 puts ("Outside available Flash\n"); 200 break; 201 case ERR_ALIGN: 202 puts ("Start and/or end address not on sector boundary\n"); 203 break; 204 case ERR_UNKNOWN_FLASH_VENDOR: 205 puts ("Unknown Vendor of Flash\n"); 206 break; 207 case ERR_UNKNOWN_FLASH_TYPE: 208 puts ("Unknown Type of Flash\n"); 209 break; 210 case ERR_PROG_ERROR: 211 puts ("General Flash Programming Error\n"); 212 break; 213 case ERR_ABORTED: 214 puts("Flash Programming Aborted\n"); 215 break; 216 default: 217 printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err); 218 break; 219 } 220 } 221 222 /*----------------------------------------------------------------------- 223 */ 224 #endif /* !CONFIG_SYS_NO_FLASH */ 225