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