FreeCalypso > hg > freecalypso-tools
comparison loadtools/flutil.c @ 506:0dd2c87c1b63
fc-loadtool flash support overhaul
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 28 May 2019 05:12:47 +0000 |
parents | 7bf0d909c87e |
children | ba9523ca6ed8 |
comparison
equal
deleted
inserted
replaced
505:7bf0d909c87e | 506:0dd2c87c1b63 |
---|---|
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include "flash.h" | 9 #include "flash.h" |
10 | 10 |
11 extern struct flash_bank_info flash_bank_info[2]; | 11 extern struct flash_bank_info flash_bank_info[2]; |
12 extern struct flash_cmdset flash_cmdset_amd; | |
13 extern struct flash_cmdset flash_cmdset_intel; | |
14 | |
15 static int | |
16 cfi_read_byte(bi, off, ret16p) | |
17 struct flash_bank_info *bi; | |
18 int off; | |
19 uint16_t *ret16p; | |
20 { | |
21 return do_r16(bi->base_addr + (off << 1), ret16p); | |
22 } | |
23 | |
24 static int | |
25 cfi_read_twobyte(bi, off, retptr) | |
26 struct flash_bank_info *bi; | |
27 int off; | |
28 uint16_t *retptr; | |
29 { | |
30 uint16_t lo, hi; | |
31 | |
32 if (cfi_read_byte(bi, off, &lo) < 0) | |
33 return(-1); | |
34 lo &= 0xFF; | |
35 if (cfi_read_byte(bi, off + 1, &hi) < 0) | |
36 return(-1); | |
37 hi &= 0xFF; | |
38 *retptr = (hi << 8) | lo; | |
39 return(0); | |
40 } | |
41 | |
42 flash_get_cfi(bank) | |
43 { | |
44 struct flash_bank_info *bi; | |
45 struct flash_geom *geom; | |
46 struct flash_region_desc *reg; | |
47 int nr; | |
48 uint16_t rdval, cmdset_id; | |
49 uint32_t size_check; | |
50 | |
51 bi = flash_bank_info + bank; | |
52 if (bi->geom) | |
53 return(0); | |
54 printf("Performing CFI query\n"); | |
55 if (do_w16(bi->base_addr + 0xAA, 0x98)) { | |
56 fprintf(stderr, "unexpected response to w16 - aborting\n"); | |
57 return(-1); | |
58 } | |
59 /* if do_r16() returns -1, error msg has already been printed */ | |
60 if (cfi_read_byte(bi, 0x10, &rdval) < 0) | |
61 return(-1); | |
62 if (rdval != 'Q') { | |
63 noqry: fprintf(stderr, "error: no QRY response from flash\n"); | |
64 amd_reset_cmd(bi); | |
65 return(-1); | |
66 } | |
67 if (cfi_read_byte(bi, 0x11, &rdval) < 0) | |
68 return(-1); | |
69 if (rdval != 'R') | |
70 goto noqry; | |
71 if (cfi_read_byte(bi, 0x12, &rdval) < 0) | |
72 return(-1); | |
73 if (rdval != 'Y') | |
74 goto noqry; | |
75 if (cfi_read_twobyte(bi, 0x13, &cmdset_id) < 0) | |
76 return(-1); | |
77 if (!bi->ops) { | |
78 switch (cmdset_id) { | |
79 case 2: | |
80 bi->ops = &flash_cmdset_amd; | |
81 break; | |
82 case 3: | |
83 bi->ops = &flash_cmdset_intel; | |
84 break; | |
85 default: | |
86 fprintf(stderr, "error: command set %04X unsupported\n", | |
87 cmdset_id); | |
88 amd_reset_cmd(bi); | |
89 return(-1); | |
90 } | |
91 } | |
92 geom = malloc(sizeof(struct flash_geom)); | |
93 if (!geom) { | |
94 fprintf(stderr, | |
95 "unable to malloc buffer for flash bank %d CFI geometry structure\n", | |
96 bank); | |
97 bi->ops->reset_cmd(bi); | |
98 return(-1); | |
99 } | |
100 /* total device size */ | |
101 if (cfi_read_byte(bi, 0x27, &rdval) < 0) { | |
102 free_and_immed_out: | |
103 free(geom); | |
104 return(-1); | |
105 } | |
106 if (rdval < 20 || rdval > 24) { | |
107 fprintf(stderr, | |
108 "error: CFI reports unreasonable device size\n"); | |
109 free_and_clean_out: | |
110 free(geom); | |
111 bi->ops->reset_cmd(bi); | |
112 return(-1); | |
113 } | |
114 geom->total_size = 1 << rdval; | |
115 if (geom->total_size > bi->bank_desc->align_size) { | |
116 fprintf(stderr, | |
117 "error: CFI device size 0x%lx exceeds configured maximum 0x%lx\n", | |
118 (u_long) geom->total_size, bi->bank_desc->align_size); | |
119 goto free_and_clean_out; | |
120 } | |
121 if (cfi_read_byte(bi, 0x2C, &rdval) < 0) | |
122 goto free_and_immed_out; | |
123 if (rdval < 1 || rdval > CFI_MAX_REGIONS) { | |
124 fprintf(stderr, | |
125 "error: CFI reports unreasonable # of erase regions\n"); | |
126 goto free_and_clean_out; | |
127 } | |
128 geom->nregions = rdval; | |
129 geom->total_sectors = 0; | |
130 size_check = 0; | |
131 for (nr = 0; nr < geom->nregions; nr++) { | |
132 reg = geom->regions + nr; | |
133 if (cfi_read_twobyte(bi, 0x2D + nr*4, &rdval) < 0) | |
134 goto free_and_immed_out; | |
135 if (rdval > 255) { | |
136 fprintf(stderr, | |
137 "error: CFI reports unreasonable # of sectors in region %d\n", | |
138 nr); | |
139 goto free_and_clean_out; | |
140 } | |
141 reg->nsectors = rdval + 1; | |
142 geom->total_sectors += reg->nsectors; | |
143 if (cfi_read_twobyte(bi, 0x2F + nr*4, &rdval) < 0) | |
144 goto free_and_immed_out; | |
145 if (rdval < 0x20 || rdval > 0x400) { | |
146 fprintf(stderr, | |
147 "error: CFI reports unreasonable sector size in region %d\n", | |
148 nr); | |
149 goto free_and_clean_out; | |
150 } | |
151 reg->sector_size = rdval << 8; | |
152 size_check += reg->sector_size * reg->nsectors; | |
153 } | |
154 if (bi->ops->reset_cmd(bi) < 0) { | |
155 /* error msg already printed */ | |
156 free(geom); | |
157 return(-1); | |
158 } | |
159 if (size_check != geom->total_size) { | |
160 fprintf(stderr, | |
161 "CFI error: added size of erase regions (%lx) != reported device size (%lx)\n", | |
162 (u_long) size_check, (u_long) geom->total_size); | |
163 free(geom); | |
164 return(-1); | |
165 } | |
166 /* all checks passed */ | |
167 bi->geom = geom; | |
168 printf( | |
169 "CFI query successful: total size %lx, %u sectors, command set style %04X\n", | |
170 (u_long) geom->total_size, geom->total_sectors, cmdset_id); | |
171 return(1); | |
172 } | |
173 | 12 |
174 get_flash_sector_table(bank) | 13 get_flash_sector_table(bank) |
175 { | 14 { |
176 struct flash_bank_info *bi; | 15 struct flash_bank_info *bi; |
177 struct flash_geom *geom; | 16 struct flash_geom *geom; |
181 int nr, i; | 20 int nr, i; |
182 | 21 |
183 bi = flash_bank_info + bank; | 22 bi = flash_bank_info + bank; |
184 if (bi->sectors) | 23 if (bi->sectors) |
185 return(0); | 24 return(0); |
186 i = flash_get_cfi(bank); | 25 i = flash_detect(bank, 0); |
187 if (i < 0) | 26 if (i < 0) |
188 return(i); | 27 return(i); |
189 geom = bi->geom; | 28 geom = bi->geom; |
190 sp = (struct sector_info *) malloc(sizeof(struct sector_info) | 29 sp = (struct sector_info *) malloc(sizeof(struct sector_info) |
191 * (geom->total_sectors + 1)); | 30 * (geom->total_sectors + 1)); |
289 else | 128 else |
290 sprintf(s, "%02X%02X", dp[1], dp[0]); | 129 sprintf(s, "%02X%02X", dp[1], dp[0]); |
291 } | 130 } |
292 *s = '\0'; | 131 *s = '\0'; |
293 } | 132 } |
294 | |
295 flash_id_check(bank, repeat) | |
296 { | |
297 struct flash_bank_info *bi; | |
298 struct flash_bank_desc *bd; | |
299 struct flash_idcheck *id; | |
300 int stat, fail; | |
301 uint16_t rdval; | |
302 unsigned cnt; | |
303 | |
304 bi = flash_bank_info + bank; | |
305 if (bi->idcheck_done && !repeat) | |
306 return(0); | |
307 bd = bi->bank_desc; | |
308 if (!bd->idcheck_table || !bd->idcheck_num) | |
309 return(0); | |
310 printf("Performing flash ID check\n"); | |
311 stat = do_w16(bi->base_addr + 0xAAA, 0xAA); | |
312 if (stat) { | |
313 bad_w16: fprintf(stderr, | |
314 "unexpected response to w16 in read ID cmd sequence - aborting\n"); | |
315 return(-1); | |
316 } | |
317 stat = do_w16(bi->base_addr + 0x554, 0x55); | |
318 if (stat) | |
319 goto bad_w16; | |
320 stat = do_w16(bi->base_addr + 0xAAA, 0x90); | |
321 if (stat) | |
322 goto bad_w16; | |
323 id = bd->idcheck_table; | |
324 fail = 0; | |
325 for (cnt = 0; cnt < bd->idcheck_num; cnt++) { | |
326 stat = do_r16(bi->base_addr + id->offset, &rdval); | |
327 if (stat) | |
328 return(stat); /* error msg already printed */ | |
329 printf("offset %02X: %04X -- ", (int)id->offset, (int)rdval); | |
330 if (rdval == id->expect_val) | |
331 printf("PASS\n"); | |
332 else { | |
333 printf("FAIL: expected %04X\n", (int)id->expect_val); | |
334 fail = 1; | |
335 break; | |
336 } | |
337 id++; | |
338 } | |
339 if (fail) | |
340 return(-1); | |
341 if (bi->ops->reset_cmd(bi) < 0) { | |
342 /* error msg already printed */ | |
343 return(-1); | |
344 } | |
345 bi->idcheck_done = 1; | |
346 return(0); | |
347 } |