FreeCalypso > hg > freecalypso-tools
comparison loadtools/flamdsec.c @ 983:0407d14fb854
PL-J flash PPB ops: rework for full verification of lock state
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 02 Dec 2023 08:22:00 +0000 |
parents | 1c5b485f10ba |
children | 84c9869a3659 |
comparison
equal
deleted
inserted
replaced
982:1c5b485f10ba | 983:0407d14fb854 |
---|---|
6 | 6 |
7 #include <sys/types.h> | 7 #include <sys/types.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 #include <stdlib.h> | 10 #include <stdlib.h> |
11 #include <string.h> | |
12 #include <strings.h> | |
11 #include <unistd.h> | 13 #include <unistd.h> |
12 #include "flash.h" | 14 #include "flash.h" |
13 | 15 |
14 extern struct flash_bank_info flash_bank_info[2]; | 16 extern struct flash_bank_info flash_bank_info[2]; |
15 | 17 |
179 } | 181 } |
180 return(0); | 182 return(0); |
181 } | 183 } |
182 | 184 |
183 /* | 185 /* |
186 * Here comes a version of the above lock-state checking code, | |
187 * modified for use from within ppb-program-all and ppb-erase-all | |
188 * functions for chips that don't do this work internally. | |
189 */ | |
190 | |
191 static | |
192 int_lock_state_check(bi, sought_state) | |
193 struct flash_bank_info *bi; | |
194 { | |
195 struct amd_lock_info *li = bi->amd_lock; | |
196 struct lock_group_desc *grp; | |
197 uint32_t offset, part_addr; | |
198 uint16_t word; | |
199 unsigned ng, nb; | |
200 int lock_state; | |
201 | |
202 offset = 0; | |
203 for (ng = 0; ng < li->ngroups; ng++) { | |
204 grp = li->groups + ng; | |
205 if (grp->part_begin) { | |
206 part_addr = bi->base_addr + offset; | |
207 if (issue_read_id(part_addr) < 0) | |
208 return(-1); | |
209 } | |
210 for (nb = 0; nb < grp->nblocks; nb++) { | |
211 if (do_r16(bi->base_addr + offset + 4, &word) < 0) | |
212 return(-1); | |
213 lock_state = word & 1; | |
214 if (lock_state != sought_state) | |
215 break; | |
216 offset += grp->block_size; | |
217 } | |
218 if (lock_state != sought_state) { | |
219 if (issue_reset_cmd(part_addr) < 0) | |
220 return(-1); | |
221 return(0); | |
222 } | |
223 if (grp->part_end) { | |
224 if (issue_reset_cmd(part_addr) < 0) | |
225 return(-1); | |
226 } | |
227 } | |
228 return(1); | |
229 } | |
230 | |
231 /* | |
184 * Spansion PL-J PPB write functions, referenced from lock_info structures | 232 * Spansion PL-J PPB write functions, referenced from lock_info structures |
185 * in fldevs.c device descriptions. | 233 * in fldevs.c device descriptions. |
186 */ | 234 */ |
187 | 235 |
188 static | 236 static |
226 continue; | 274 continue; |
227 printf("PPB 0x%X programmed with %u pulse%s\n", sector_addr, | 275 printf("PPB 0x%X programmed with %u pulse%s\n", sector_addr, |
228 pulsecnt, pulsecnt > 1 ? "s" : ""); | 276 pulsecnt, pulsecnt > 1 ? "s" : ""); |
229 return amd_reset_cmd(bi); | 277 return amd_reset_cmd(bi); |
230 } | 278 } |
231 printf("PPB 0x%X programming FAILED, tried %u pulses\n", sector_addr, | 279 fprintf(stderr, "PPB 0x%X programming FAILED, tried %u pulses\n", |
232 pulsecnt); | 280 sector_addr, pulsecnt); |
233 return(-1); | 281 return(-1); |
234 } | 282 } |
235 | 283 |
236 plj_ppb_program_all_single(bank) | 284 plj_ppb_program_all(bi) |
237 { | 285 struct flash_bank_info *bi; |
238 struct flash_bank_info *bi = flash_bank_info + bank; | 286 { |
239 struct amd_lock_info *li = bi->amd_lock; | 287 struct amd_lock_info *li = bi->amd_lock; |
240 struct lock_group_desc *grp; | 288 struct lock_group_desc *grp; |
241 uint32_t offset; | 289 uint32_t offset; |
242 unsigned ng, nb; | 290 unsigned ng, nb; |
243 int rc; | 291 int rc; |
250 if (rc < 0) | 298 if (rc < 0) |
251 return(rc); | 299 return(rc); |
252 offset += grp->block_size; | 300 offset += grp->block_size; |
253 } | 301 } |
254 } | 302 } |
255 return(0); | 303 printf("Verifying PPB programming\n"); |
256 } | 304 rc = int_lock_state_check(bi, 1); |
257 | |
258 plj_ppb_program_all_dualbank(reqbank) | |
259 { | |
260 int altbank = !reqbank; | |
261 int rc; | |
262 | |
263 if (flash_detect(altbank, 0) < 0) | |
264 return(-1); | |
265 if (flash_bank_info[0].device != flash_bank_info[1].device) { | |
266 fprintf(stderr, "error: mismatch between two flash banks\n"); | |
267 return(-1); | |
268 } | |
269 printf("Programming all PPBs in flash bank 0\n"); | |
270 rc = plj_ppb_program_all_single(0); | |
271 if (rc < 0) | 305 if (rc < 0) |
272 return(-1); | 306 return(rc); |
273 printf("Programming all PPBs in flash bank 1\n"); | 307 if (rc) |
274 rc = plj_ppb_program_all_single(1); | 308 return(0); |
275 if (rc < 0) | 309 fprintf(stderr, "flash error: one or more PPBs failed to program\n"); |
276 return(-1); | 310 return(-1); |
277 return(0); | 311 } |
278 } | 312 |
279 | 313 static |
280 static | 314 plj_ppb_erase_cycle(bi) |
281 plj_ppb_erase_cycle(bank) | 315 struct flash_bank_info *bi; |
282 { | 316 { |
283 struct flash_bank_info *bi = flash_bank_info + bank; | |
284 uint16_t stat; | 317 uint16_t stat; |
285 unsigned pulsecnt; | 318 unsigned pulsecnt; |
286 int rc; | 319 int rc; |
287 | 320 |
288 printf("Performing PPB erase cycle\n"); | 321 printf("Performing PPB erase cycle\n"); |
295 continue; | 328 continue; |
296 printf("PPB erase cycle succeeded after %u pulse%s\n", | 329 printf("PPB erase cycle succeeded after %u pulse%s\n", |
297 pulsecnt, pulsecnt > 1 ? "s" : ""); | 330 pulsecnt, pulsecnt > 1 ? "s" : ""); |
298 return amd_reset_cmd(bi); | 331 return amd_reset_cmd(bi); |
299 } | 332 } |
300 printf("PPB erase cycle FAILED, tried %u pulses\n", pulsecnt); | 333 fprintf(stderr, "PPB erase cycle FAILED, tried %u pulses\n", pulsecnt); |
301 return(-1); | 334 return(-1); |
302 } | 335 } |
303 | 336 |
304 plj_ppb_erase_all_single(bank) | 337 plj_ppb_erase_all_single(bank, raw_mode) |
305 { | 338 { |
339 struct flash_bank_info *bi = flash_bank_info + bank; | |
340 unsigned pulsecnt; | |
341 uint16_t stat; | |
306 int rc; | 342 int rc; |
307 | 343 |
344 if (raw_mode) | |
345 return plj_ppb_erase_cycle(bi); | |
308 printf("Programming all PPBs before erase cycle\n"); | 346 printf("Programming all PPBs before erase cycle\n"); |
309 rc = plj_ppb_program_all_single(bank); | 347 rc = plj_ppb_program_all(bi); |
310 if (rc < 0) | 348 if (rc < 0) |
311 return(-1); | 349 return(-1); |
312 return plj_ppb_erase_cycle(bank); | 350 printf("Entering PPB erase and verify loop\n"); |
313 } | 351 for (pulsecnt = 0; ; ) { |
314 | 352 if (pulsecnt >= 1000) { |
315 plj_ppb_erase_all_dualbank(reqbank) | 353 fprintf(stderr, |
316 { | 354 "flash error: unable to complete PPB erase after %u pulses\n", |
355 pulsecnt); | |
356 return(-1); | |
357 } | |
358 rc = plj_ppb_write_op(bi->base_addr, 1, &stat); | |
359 if (rc < 0) | |
360 return(rc); | |
361 pulsecnt++; | |
362 if (stat & 1) | |
363 continue; | |
364 putchar('.'); | |
365 fflush(stdout); | |
366 rc = amd_reset_cmd(bi); | |
367 if (rc < 0) | |
368 return(rc); | |
369 rc = int_lock_state_check(bi, 0); | |
370 if (rc < 0) | |
371 return(rc); | |
372 if (rc) | |
373 break; | |
374 } | |
375 printf("\nPPB erase complete, total pulses: %u\n", pulsecnt); | |
376 return(0); | |
377 } | |
378 | |
379 plj_ppb_erase_all_dualbank(reqbank, raw_mode) | |
380 { | |
381 int altbank = !reqbank; | |
382 unsigned pulsecnt; | |
383 uint16_t stat; | |
317 int rc; | 384 int rc; |
318 | 385 |
319 rc = plj_ppb_program_all_dualbank(reqbank); | 386 if (flash_detect(altbank, 0) < 0) |
387 return(-1); | |
388 if (flash_bank_info[0].device != flash_bank_info[1].device) { | |
389 fprintf(stderr, "error: mismatch between two flash banks\n"); | |
390 return(-1); | |
391 } | |
392 if (raw_mode) | |
393 return plj_ppb_erase_cycle(flash_bank_info + reqbank); | |
394 printf("Programming all PPBs in flash bank 0\n"); | |
395 rc = plj_ppb_program_all(&flash_bank_info[0]); | |
320 if (rc < 0) | 396 if (rc < 0) |
321 return(-1); | 397 return(-1); |
322 return plj_ppb_erase_cycle(reqbank); | 398 printf("Programming all PPBs in flash bank 1\n"); |
399 rc = plj_ppb_program_all(&flash_bank_info[1]); | |
400 if (rc < 0) | |
401 return(-1); | |
402 printf("Entering PPB erase and verify loop\n"); | |
403 for (pulsecnt = 0; ; ) { | |
404 if (pulsecnt >= 1000) { | |
405 fprintf(stderr, | |
406 "flash error: unable to complete PPB erase after %u pulses\n", | |
407 pulsecnt); | |
408 return(-1); | |
409 } | |
410 rc = plj_ppb_write_op(flash_bank_info[0].base_addr, 1, &stat); | |
411 if (rc < 0) | |
412 return(rc); | |
413 pulsecnt++; | |
414 if (stat & 1) | |
415 continue; | |
416 putchar('.'); | |
417 fflush(stdout); | |
418 rc = amd_reset_cmd(&flash_bank_info[0]); | |
419 if (rc < 0) | |
420 return(rc); | |
421 rc = int_lock_state_check(&flash_bank_info[0], 0); | |
422 if (rc < 0) | |
423 return(rc); | |
424 if (!rc) | |
425 continue; | |
426 rc = int_lock_state_check(&flash_bank_info[1], 0); | |
427 if (rc < 0) | |
428 return(rc); | |
429 if (rc) | |
430 break; | |
431 } | |
432 printf("\nPPB erase complete, total pulses: %u\n", pulsecnt); | |
433 return(0); | |
323 } | 434 } |
324 | 435 |
325 /* | 436 /* |
326 * Front end functions for PPB operation commands. | 437 * Front end functions for PPB operation commands. |
327 */ | 438 */ |
388 if (!li || !li->ppb_program_all) { | 499 if (!li || !li->ppb_program_all) { |
389 fprintf(stderr, | 500 fprintf(stderr, |
390 "Operation not supported for this flash chip type\n"); | 501 "Operation not supported for this flash chip type\n"); |
391 return(-1); | 502 return(-1); |
392 } | 503 } |
393 return li->ppb_program_all(bank); | 504 return li->ppb_program_all(bi); |
394 } | 505 } |
395 | 506 |
396 flashcmd_ppb_erase_all(argc, argv, bank) | 507 flashcmd_ppb_erase_all(argc, argv, bank) |
397 char **argv; | 508 char **argv; |
398 { | 509 { |
399 struct flash_bank_info *bi; | 510 struct flash_bank_info *bi; |
400 struct amd_lock_info *li; | 511 struct amd_lock_info *li; |
401 | 512 int raw_mode; |
402 if (argc > 2) { | 513 |
403 fprintf(stderr, "error: too many arguments\n"); | 514 switch (argc) { |
515 case 2: | |
516 raw_mode = 0; | |
517 break; | |
518 case 3: | |
519 if (!strcmp(argv[2], "raw")) { | |
520 raw_mode = 1; | |
521 break; | |
522 } | |
523 /* FALL THRU */ | |
524 default: | |
525 fprintf(stderr, "usage: %s %s [raw]\n", argv[0], argv[1]); | |
404 return(-1); | 526 return(-1); |
405 } | 527 } |
406 if (flash_detect(bank, 0) < 0) | 528 if (flash_detect(bank, 0) < 0) |
407 return(-1); | 529 return(-1); |
408 bi = flash_bank_info + bank; | 530 bi = flash_bank_info + bank; |
410 if (!li || !li->ppb_erase_all) { | 532 if (!li || !li->ppb_erase_all) { |
411 fprintf(stderr, | 533 fprintf(stderr, |
412 "Operation not supported for this flash chip type\n"); | 534 "Operation not supported for this flash chip type\n"); |
413 return(-1); | 535 return(-1); |
414 } | 536 } |
415 return li->ppb_erase_all(bank); | 537 return li->ppb_erase_all(bank, raw_mode); |
416 } | 538 } |