FreeCalypso > hg > freecalypso-sw
comparison loadtools/ltflash.c @ 400:f027c6fbe37e
fc-loadtool flash: first round of refactoring for CFI
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 15 Jun 2014 20:05:54 +0000 |
parents | cd12d1049f91 |
children | 7ceeec049be4 |
comparison
equal
deleted
inserted
replaced
399:d26a9e3de626 | 400:f027c6fbe37e |
---|---|
1 /* | 1 /* |
2 * In this module we are going to implement the flash operation commands | 2 * This module contains the "core" of fc-loadtool flash operations; |
3 * of fc-loadtool. | 3 * fl*.c modules contain the rest. |
4 */ | 4 */ |
5 | 5 |
6 #include <sys/types.h> | 6 #include <sys/types.h> |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include "flash.h" | 12 #include "flash.h" |
13 | 13 |
14 /* K5A32xx device description */ | 14 /* K5A32xx device description */ |
15 | 15 |
16 static struct flash_region_desc k5a32xx_topboot_regions[] = { | 16 static struct cfi_info k5a32xx_topboot_hardcfi = { |
17 /* 4 MiB total, 64 KiB sectors except for the boot block of 8x 8 KiB */ | 17 .cmdset_style = 2, |
18 {0x10000, 63}, | 18 .total_size = 0x400000, |
19 {0x2000, 8}, | 19 .nregions = 2, |
20 {0, 0} /* array terminator */ | 20 .regions = {0x10000, 63, 0x2000, 8}, |
21 .total_sectors = 71 | |
21 }; | 22 }; |
22 | 23 |
23 static struct flash_idcheck k5a32xx_topboot_idcheck[2] = { | 24 static struct flash_idcheck k5a32xx_topboot_idcheck[2] = { |
24 {0x00, 0x00EC}, | 25 {0x00, 0x00EC}, |
25 {0x02, 0x22A0} | 26 {0x02, 0x22A0} |
26 }; | 27 }; |
27 | 28 |
28 static struct flash_bank_desc k5a32xx_topboot_bankdesc = { | 29 static struct flash_bank_desc k5a32xx_topboot_bankdesc = { |
29 k5a32xx_topboot_regions, 0xFFF00000, k5a32xx_topboot_idcheck, 2 | 30 0x400000, &k5a32xx_topboot_hardcfi, k5a32xx_topboot_idcheck, 2 |
30 }; | 31 }; |
31 | 32 |
32 /* S{29,71}PL129N device description */ | 33 /* S{29,71}PL129N device description */ |
33 | 34 |
34 static struct flash_region_desc pl129n_ce1_regions[] = { | 35 static struct cfi_info pl129n_ce1_hardcfi = { |
35 /* 4 sectors of 64 KiB each at the beginning, then 256 KiB sectors */ | 36 .cmdset_style = 2, |
36 {0x10000, 4}, | 37 .total_size = 0x800000, |
37 {0x40000, 31}, | 38 .nregions = 2, |
38 {0, 0} /* array terminator */ | 39 .regions = {0x10000, 4, 0x40000, 31}, |
39 }; | 40 .total_sectors = 35 |
40 | 41 }; |
41 static struct flash_region_desc pl129n_ce2_regions[] = { | 42 |
42 /* the other way around now */ | 43 static struct cfi_info pl129n_ce2_hardcfi = { |
43 {0x40000, 31}, | 44 .cmdset_style = 2, |
44 {0x10000, 4}, | 45 .total_size = 0x800000, |
45 {0, 0} /* array terminator */ | 46 .nregions = 2, |
47 .regions = {0x40000, 31, 0x10000, 4}, | |
48 .total_sectors = 35 | |
46 }; | 49 }; |
47 | 50 |
48 static struct flash_idcheck pl129n_idcheck[4] = { | 51 static struct flash_idcheck pl129n_idcheck[4] = { |
49 {0x00, 0x0001}, | 52 {0x00, 0x0001}, |
50 {0x02, 0x227E}, | 53 {0x02, 0x227E}, |
51 {0x1C, 0x2221}, | 54 {0x1C, 0x2221}, |
52 {0x1E, 0x2200} | 55 {0x1E, 0x2200} |
53 }; | 56 }; |
54 | 57 |
55 static struct flash_bank_desc pl129n_banks[2] = { | 58 static struct flash_bank_desc pl129n_banks[2] = { |
56 {pl129n_ce1_regions, 0xFFFC0000, pl129n_idcheck, 4}, | 59 {0x800000, &pl129n_ce1_hardcfi, pl129n_idcheck, 4}, |
57 {pl129n_ce2_regions, 0xFFFC0000, pl129n_idcheck, 4} | 60 {0x800000, &pl129n_ce2_hardcfi, pl129n_idcheck, 4} |
58 }; | 61 }; |
59 | 62 |
60 /* list of supported flash devices */ | 63 /* list of supported flash devices */ |
61 | 64 |
62 struct flash_device_desc flash_device_list[] = { | 65 struct flash_device_desc flash_device_list[] = { |
128 filename_for_errs, lineno_for_errs); | 131 filename_for_errs, lineno_for_errs); |
129 exit(1); | 132 exit(1); |
130 } | 133 } |
131 /* the rest comes from the flash device type */ | 134 /* the rest comes from the flash device type */ |
132 bi->bank_desc = selected_flash_device->bank_desc + bank; | 135 bi->bank_desc = selected_flash_device->bank_desc + bank; |
133 compute_flash_totsize_nsecs(bank); | 136 if (bi->base_addr & (bi->bank_desc->align_size - 1)) { |
134 if (count_ones(bi->total_size) != 1) { | |
135 fprintf(stderr, | |
136 "fc-loadtool internal bug: flash bank %d size for %s is not a power of 2\n", | |
137 bank, selected_flash_device->name); | |
138 exit(1); | |
139 } | |
140 if (bi->base_addr & (bi->total_size - 1)) { | |
141 fprintf(stderr, | 137 fprintf(stderr, |
142 "%s line %d: flash bank %d base addr is not aligned to the bank size (0x%lx)\n", | 138 "%s line %d: flash bank %d base addr is not aligned to the bank size (0x%lx)\n", |
143 filename_for_errs, lineno_for_errs, bank, | 139 filename_for_errs, lineno_for_errs, bank, |
144 (u_long) bi->total_size); | 140 (u_long) bi->bank_desc->align_size); |
145 exit(1); | 141 exit(1); |
146 } | 142 } |
143 bi->cfi = bi->bank_desc->hard_cfi; | |
147 } | 144 } |
148 while (isspace(*cp)) | 145 while (isspace(*cp)) |
149 cp++; | 146 cp++; |
150 if (*cp && *cp != '#') { | 147 if (*cp && *cp != '#') { |
151 fprintf(stderr, | 148 fprintf(stderr, |
169 return(-1); | 166 return(-1); |
170 } | 167 } |
171 offset = strtoul(argv[2], &strtoul_endp, 16); | 168 offset = strtoul(argv[2], &strtoul_endp, 16); |
172 if (*strtoul_endp) | 169 if (*strtoul_endp) |
173 goto inv; | 170 goto inv; |
171 if (flash_get_cfi(bank) < 0) | |
172 return(-1); | |
174 bi = flash_bank_info + bank; | 173 bi = flash_bank_info + bank; |
175 if (offset >= bi->total_size) { | 174 if (offset >= bi->cfi->total_size) { |
176 fprintf(stderr, | 175 fprintf(stderr, |
177 "error: specified offset exceeds flash bank size (0x%lx)\n", | 176 "error: specified offset exceeds flash bank size (0x%lx)\n", |
178 (u_long) bi->total_size); | 177 (u_long) bi->cfi->total_size); |
179 return(-1); | 178 return(-1); |
180 } | 179 } |
181 len = strtoul(argv[3], &strtoul_endp, 16); | 180 len = strtoul(argv[3], &strtoul_endp, 16); |
182 if (*strtoul_endp) | 181 if (*strtoul_endp) |
183 goto inv; | 182 goto inv; |
184 if (len > bi->total_size - offset) { | 183 if (len > bi->cfi->total_size - offset) { |
185 fprintf(stderr, | 184 fprintf(stderr, |
186 "error: specified offset+length exceed flash bank size (0x%lx)\n", | 185 "error: specified offset+length exceed flash bank size (0x%lx)\n", |
187 (u_long) bi->total_size); | 186 (u_long) bi->cfi->total_size); |
188 return(-1); | 187 return(-1); |
189 } | 188 } |
190 sprintf(targ_start, "%lx", (u_long) bi->base_addr + offset); | 189 sprintf(targ_start, "%lx", (u_long) bi->base_addr + offset); |
191 sprintf(targ_len, "%lx", len); | 190 sprintf(targ_len, "%lx", len); |
192 targv[0] = "blankchk"; | 191 targv[0] = "blankchk"; |
210 if (argc < 3 || argc > 5) { | 209 if (argc < 3 || argc > 5) { |
211 inv: fprintf(stderr, "usage: %s %s outfile [offset [length]]\n", | 210 inv: fprintf(stderr, "usage: %s %s outfile [offset [length]]\n", |
212 argv[0], argv[1]); | 211 argv[0], argv[1]); |
213 return(-1); | 212 return(-1); |
214 } | 213 } |
214 if (flash_get_cfi(bank) < 0) | |
215 return(-1); | |
215 bi = flash_bank_info + bank; | 216 bi = flash_bank_info + bank; |
216 if (argc >= 4) { | 217 if (argc >= 4) { |
217 offset = strtoul(argv[3], &strtoul_endp, 16); | 218 offset = strtoul(argv[3], &strtoul_endp, 16); |
218 if (*strtoul_endp) | 219 if (*strtoul_endp) |
219 goto inv; | 220 goto inv; |
220 if (offset >= bi->total_size) { | 221 if (offset >= bi->cfi->total_size) { |
221 fprintf(stderr, | 222 fprintf(stderr, |
222 "error: specified offset exceeds flash bank size (0x%lx)\n", | 223 "error: specified offset exceeds flash bank size (0x%lx)\n", |
223 (u_long) bi->total_size); | 224 (u_long) bi->cfi->total_size); |
224 return(-1); | 225 return(-1); |
225 } | 226 } |
226 } else | 227 } else |
227 offset = 0; | 228 offset = 0; |
228 maxlen = bi->total_size - offset; | 229 maxlen = bi->cfi->total_size - offset; |
229 if (argc >= 5) { | 230 if (argc >= 5) { |
230 dumplen = strtoul(argv[4], &strtoul_endp, 16); | 231 dumplen = strtoul(argv[4], &strtoul_endp, 16); |
231 if (*strtoul_endp) | 232 if (*strtoul_endp) |
232 goto inv; | 233 goto inv; |
233 if (dumplen > maxlen) { | 234 if (dumplen > maxlen) { |
234 fprintf(stderr, | 235 fprintf(stderr, |
235 "error: specified offset+length exceed flash bank size (0x%lx)\n", | 236 "error: specified offset+length exceed flash bank size (0x%lx)\n", |
236 (u_long) bi->total_size); | 237 (u_long) bi->cfi->total_size); |
237 return(-1); | 238 return(-1); |
238 } | 239 } |
239 } else | 240 } else |
240 dumplen = maxlen; | 241 dumplen = maxlen; |
241 switch (argv[1][5]) { | 242 switch (argv[1][5]) { |
269 return(-1); | 270 return(-1); |
270 } | 271 } |
271 bi = flash_bank_info + bank; | 272 bi = flash_bank_info + bank; |
272 printf("Flash device type: %s\n", selected_flash_device->name); | 273 printf("Flash device type: %s\n", selected_flash_device->name); |
273 printf("Bank %d base address: %08lX\n", bank, (u_long) bi->base_addr); | 274 printf("Bank %d base address: %08lX\n", bank, (u_long) bi->base_addr); |
274 printf("Bank %d total size: %lx\n", bank, (u_long) bi->total_size); | 275 if (flash_get_cfi(bank) < 0) |
275 printf("Sectors in bank %d: %u\n", bank, bi->nsectors); | 276 return(-1); |
277 printf("Bank %d total size: %lx\n", bank, (u_long) bi->cfi->total_size); | |
278 printf("Sectors in bank %d: %u (%u regions)\n", bank, | |
279 bi->cfi->total_sectors, bi->cfi->nregions); | |
276 flash_id_check(bank, 1); | 280 flash_id_check(bank, 1); |
277 if (selected_flash_device->nbanks == 2 && !bank) | 281 if (selected_flash_device->nbanks == 2 && !bank) |
278 printf("\nFlash device has 2 banks; flash2 command available\n"); | 282 printf("\nFlash device has 2 banks; flash2 command available\n"); |
279 return(0); | 283 return(0); |
280 } | 284 } |
283 char **argv; | 287 char **argv; |
284 { | 288 { |
285 char *targv[4], targ_base[10]; | 289 char *targv[4], targ_base[10]; |
286 int stat; | 290 int stat; |
287 | 291 |
292 if (flash_get_cfi(bank) < 0) | |
293 return(-1); | |
294 if (flash_bank_info[bank].cfi->cmdset_style != 2) { | |
295 fprintf(stderr, | |
296 "error: this command is currently only implemented for AMD-style flash\n"); | |
297 return(-1); | |
298 } | |
288 if (argc != 4) { | 299 if (argc != 4) { |
289 inv: fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n", | 300 fprintf(stderr, "usage: %s %s hex-offset hex-data-string\n", |
290 argv[0], argv[1]); | 301 argv[0], argv[1]); |
291 return(-1); | 302 return(-1); |
292 } | 303 } |
293 sprintf(targ_base, "%lx", (u_long) flash_bank_info[bank].base_addr); | 304 sprintf(targ_base, "%lx", (u_long) flash_bank_info[bank].base_addr); |
294 targv[0] = "AMFB"; | 305 targv[0] = "AMFB"; |