comparison loadtools/flutil.c @ 0:e7502631a0f9

initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 11 Jun 2016 00:13:35 +0000
parents
children 7bf0d909c87e
comparison
equal deleted inserted replaced
-1:000000000000 0:e7502631a0f9
1 /*
2 * Miscellaneous utility functions for flash support
3 */
4
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include "flash.h"
10
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 devive 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
174 get_flash_sector_table(bank)
175 {
176 struct flash_bank_info *bi;
177 struct flash_geom *geom;
178 struct flash_region_desc *reg;
179 struct sector_info *sp;
180 uint32_t offset;
181 int nr, i;
182
183 bi = flash_bank_info + bank;
184 if (bi->sectors)
185 return(0);
186 i = flash_get_cfi(bank);
187 if (i < 0)
188 return(i);
189 geom = bi->geom;
190 sp = (struct sector_info *) malloc(sizeof(struct sector_info)
191 * (geom->total_sectors + 1));
192 if (!sp) {
193 fprintf(stderr,
194 "unable to malloc buffer for flash bank %d sector table\n",
195 bank);
196 return(-1);
197 }
198 bi->sectors = sp;
199 /* now fill it */
200 offset = 0;
201 for (nr = 0; nr < geom->nregions; nr++) {
202 reg = geom->regions + nr;
203 for (i = 0; i < reg->nsectors; i++) {
204 sp->start = offset;
205 sp->size = reg->sector_size;
206 sp++;
207 offset += reg->sector_size;
208 }
209 }
210 /* sanity checks */
211 if (sp - bi->sectors != geom->total_sectors) {
212 fprintf(stderr,
213 "BUG in get_flash_sector_table(): wrong # of sectors at the end\n");
214 abort();
215 }
216 if (offset != geom->total_size) {
217 fprintf(stderr,
218 "BUG in get_flash_sector_table(): wrong offset at the end\n");
219 abort();
220 }
221 /* finish */
222 sp->start = 0;
223 sp->size = 0;
224 return(0);
225 }
226
227 flashcmd_sectors(argc, argv, bank)
228 char **argv;
229 {
230 struct flash_bank_info *bi;
231 struct sector_info *sp;
232
233 if (argc > 2) {
234 fprintf(stderr, "error: too many arguments\n");
235 return(-1);
236 }
237 if (get_flash_sector_table(bank) < 0)
238 return(-1);
239 bi = flash_bank_info + bank;
240 printf("%u sectors in flash bank %d:\n", bi->geom->total_sectors, bank);
241 printf("Offset Size\n");
242 for (sp = bi->sectors; sp->size; sp++)
243 printf("%08lX %lx\n", (u_long) sp->start, (u_long) sp->size);
244 return(0);
245 }
246
247 get_flash_sector_range(bi, useroff, userlen, startp, endp)
248 struct flash_bank_info *bi;
249 u_long useroff, userlen;
250 struct sector_info **startp, **endp;
251 {
252 struct sector_info *sp;
253 uint32_t remlen;
254
255 for (sp = bi->sectors; sp->size; sp++)
256 if (sp->start == useroff)
257 break;
258 if (!sp->size) {
259 fprintf(stderr,
260 "error: specified offset not aligned to a flash sector boundary\n");
261 return(-1);
262 }
263 *startp = sp;
264 for (remlen = userlen; remlen; ) {
265 if (remlen < sp->size) {
266 fprintf(stderr,
267 "error: specified length not aligned to a flash sector boundary\n");
268 return(-1);
269 }
270 remlen -= sp->size;
271 sp++;
272 }
273 *endp = sp;
274 return(0);
275 }
276
277 build_flashw_hex_string(bin, strbuf, nwords, m0src)
278 u_char *bin;
279 char *strbuf;
280 int nwords, m0src;
281 {
282 int i;
283 u_char *dp;
284 char *s;
285
286 for (dp = bin, s = strbuf, i = 0; i < nwords; dp += 2, s += 4, i++) {
287 if (m0src)
288 sprintf(s, "%02X%02X", dp[0], dp[1]);
289 else
290 sprintf(s, "%02X%02X", dp[1], dp[0]);
291 }
292 *s = '\0';
293 }
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 /* reset flash to read mode */
340 stat = do_w16(bi->base_addr + 0xAAA, 0xF0);
341 if (stat) {
342 fprintf(stderr,
343 "unexpected response to w16 when resetting flash to read mode!\n");
344 return(-1);
345 }
346 if (fail)
347 return(-1);
348 bi->idcheck_done = 1;
349 return(0);
350 }