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";