usbboot/src/cmd.c |
28 | 28 | #include <ctype.h> |
29 | 29 | #include <byteswap.h> |
30 | 30 | #include "cmd.h" |
| 31 | #include "command_line.h" |
31 | 32 | #include "ingenic_cfg.h" |
32 | 33 | #include "ingenic_usb.h" |
33 | 34 | #include "ingenic_request.h" |
34 | 35 | #include "usb_boot_defines.h" |
35 | 36 | |
36 | | extern int com_argc; |
37 | | extern char com_argv[MAX_ARGC][MAX_COMMAND_LENGTH]; |
38 | | extern char * stage1; |
39 | | |
40 | | struct ingenic_dev ingenic_dev; |
41 | | struct hand hand; |
42 | | struct sdram_in sdram_in; |
43 | | struct nand_in nand_in; |
44 | | |
45 | | unsigned int total_size; |
46 | | unsigned char code_buf[4 * 512 * 1024]; |
47 | | unsigned char check_buf[4 * 512 * 1024]; |
48 | | unsigned char cs[16]; |
49 | | unsigned char ret[8]; |
50 | | |
51 | | static const char IMAGE_TYPE[][30] = { |
52 | | "with oob and ecc", |
53 | | "with oob and without ecc", |
54 | | "without oob", |
55 | | }; |
56 | | |
57 | | static int load_file(struct ingenic_dev *ingenic_dev, const char *file_path) |
| 37 | static int load_file(struct ingenic_dev *id, const char *file_path) |
58 | 38 | { |
59 | | struct stat fstat; |
| 39 | struct stat fst; |
| 40 | struct fw_args *fw_args_copy; |
60 | 41 | int fd, status, res = -1; |
61 | 42 | |
62 | | status = stat(file_path, &fstat); |
| 43 | status = stat(file_path, &fst); |
63 | 44 | |
64 | 45 | if (status < 0) { |
65 | 46 | fprintf(stderr, "Error - can't get file size from '%s': %s\n", |
... | ... | |
67 | 48 | goto out; |
68 | 49 | } |
69 | 50 | |
70 | | ingenic_dev->file_len = fstat.st_size; |
71 | | ingenic_dev->file_buff = code_buf; |
| 51 | id->file_len = fst.st_size; |
| 52 | id->file_buff = code_buf; |
72 | 53 | |
73 | 54 | fd = open(file_path, O_RDONLY); |
74 | 55 | |
... | ... | |
78 | 59 | goto out; |
79 | 60 | } |
80 | 61 | |
81 | | status = read(fd, ingenic_dev->file_buff, ingenic_dev->file_len); |
| 62 | status = read(fd, id->file_buff, id->file_len); |
82 | 63 | |
83 | | if (status < ingenic_dev->file_len) { |
| 64 | if (status < id->file_len) { |
84 | 65 | fprintf(stderr, "Error - can't read file '%s': %s\n", |
85 | 66 | file_path, strerror(errno)); |
86 | 67 | goto close; |
87 | 68 | } |
88 | 69 | |
89 | | struct fw_args *fw_args_copy = malloc(sizeof(struct fw_args)); |
| 70 | fw_args_copy = malloc(sizeof(struct fw_args)); |
90 | 71 | if (!fw_args_copy) |
91 | 72 | goto close; |
92 | 73 | |
... | ... | |
100 | 81 | #endif |
101 | 82 | |
102 | 83 | /* write args to code */ |
103 | | memcpy(ingenic_dev->file_buff + 8, fw_args_copy, |
| 84 | memcpy(id->file_buff + 8, fw_args_copy, |
104 | 85 | sizeof(struct fw_args)); |
105 | 86 | |
106 | 87 | free(fw_args_copy); |
... | ... | |
145 | 126 | return status; |
146 | 127 | } |
147 | 128 | |
148 | | /* after upload stage2. must init device */ |
| 129 | /* After upload stage2. we have to init the device */ |
149 | 130 | void init_cfg() |
150 | 131 | { |
| 132 | struct hand *hand_copy; |
151 | 133 | int cpu = get_ingenic_cpu(); |
152 | 134 | if (cpu != BOOT4740 && cpu != BOOT4750 && cpu != BOOT4760) { |
153 | 135 | printf(" Device unboot! boot it first!\n"); |
154 | 136 | return; |
155 | 137 | } |
156 | 138 | |
157 | | struct hand *hand_copy = malloc(sizeof(struct hand)); |
| 139 | hand_copy = malloc(sizeof(struct hand)); |
158 | 140 | if (!hand_copy) |
159 | 141 | goto xout; |
160 | 142 | |
... | ... | |
184 | 166 | #endif |
185 | 167 | |
186 | 168 | |
187 | | ingenic_dev.file_buff = hand_copy; |
| 169 | ingenic_dev.file_buff = (unsigned char *)hand_copy; |
188 | 170 | ingenic_dev.file_len = sizeof(struct hand); |
189 | 171 | if (usb_send_data_to_ingenic(&ingenic_dev) != 1) |
190 | 172 | goto xout; |
... | ... | |
246 | 228 | printf(" Comparing %d bytes - ", size); |
247 | 229 | for (i = 0; i < size; i++) { |
248 | 230 | if (org[i] != obj[i]) { |
249 | | unsigned int s = (i < 8) ? i : i - 8; // start_dump |
| 231 | unsigned int s = (i < 8) ? i : i - 8; |
250 | 232 | printf("FAIL at off %d, wrote 0x%x, read 0x%x\n", i, org[i], obj[i]); |
251 | 233 | printf(" off %d write: %02x %02x %02x %02x %02x %02x %02x %02x" |
252 | 234 | " %02x %02x %02x %02x %02x %02x %02x %02x\n", s, |
... | ... | |
265 | 247 | return 1; |
266 | 248 | } |
267 | 249 | |
268 | | int nand_markbad(struct nand_in *nand_in) |
| 250 | int nand_markbad(struct nand_in *ni) |
269 | 251 | { |
270 | 252 | int cpu = get_ingenic_cpu(); |
271 | 253 | if (cpu != BOOT4740 && cpu != BOOT4750 && cpu != BOOT4760) { |
272 | 254 | printf(" Device unboot! boot it first!\n"); |
273 | 255 | return -1; |
274 | 256 | } |
275 | | printf(" Mark bad block : %d\n",nand_in->start); |
276 | | usb_send_data_address_to_ingenic(&ingenic_dev, nand_in->start); |
| 257 | printf(" Mark bad block : %d\n",ni->start); |
| 258 | usb_send_data_address_to_ingenic(&ingenic_dev, ni->start); |
277 | 259 | usb_ingenic_nand_ops(&ingenic_dev, NAND_MARK_BAD); |
278 | 260 | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
279 | 261 | printf(" Mark bad block at %d\n",((ret[3] << 24) | |
... | ... | |
283 | 265 | return 0; |
284 | 266 | } |
285 | 267 | |
286 | | int nand_program_check(struct nand_in *nand_in, unsigned int *start_page) |
| 268 | int nand_program_check(struct nand_in *ni, unsigned int *start_page) |
287 | 269 | { |
288 | 270 | unsigned int i, page_num, cur_page = -1; |
289 | 271 | unsigned int start_addr; |
290 | 272 | unsigned short temp; |
| 273 | int cpu; |
291 | 274 | int status = -1; |
292 | 275 | |
293 | | printf(" Writing NAND page %d len %d...\n", nand_in->start, nand_in->length); |
294 | | if (nand_in->length > (unsigned int)MAX_TRANSFER_SIZE) { |
| 276 | printf(" Writing NAND page %d len %d...\n", ni->start, ni->length); |
| 277 | if (ni->length > (unsigned int)MAX_TRANSFER_SIZE) { |
295 | 278 | printf(" Buffer size too long!\n"); |
296 | 279 | goto err; |
297 | 280 | } |
298 | 281 | |
299 | | int cpu = get_ingenic_cpu(); |
| 282 | cpu = get_ingenic_cpu(); |
300 | 283 | if (cpu != BOOT4740 && cpu != BOOT4750 && cpu != BOOT4760) { |
301 | 284 | printf(" Device unboot! boot it first!\n"); |
302 | 285 | goto err; |
303 | 286 | } |
304 | 287 | |
305 | | ingenic_dev.file_buff = nand_in->buf; |
306 | | ingenic_dev.file_len = nand_in->length; |
| 288 | ingenic_dev.file_buff = ni->buf; |
| 289 | ingenic_dev.file_len = ni->length; |
307 | 290 | usb_send_data_to_ingenic(&ingenic_dev); |
308 | | for (i = 0; i < nand_in->max_chip; i++) { |
309 | | if ((nand_in->cs_map)[i] == 0) |
| 291 | for (i = 0; i < ni->max_chip; i++) { |
| 292 | if ((ni->cs_map)[i] == 0) |
310 | 293 | continue; |
311 | | if (nand_in->option == NO_OOB) { |
312 | | page_num = nand_in->length / hand.nand_ps; |
313 | | if ((nand_in->length % hand.nand_ps) !=0) |
| 294 | if (ni->option == NO_OOB) { |
| 295 | page_num = ni->length / hand.nand_ps; |
| 296 | if ((ni->length % hand.nand_ps) !=0) |
314 | 297 | page_num++; |
315 | 298 | } else { |
316 | | page_num = nand_in->length / |
| 299 | page_num = ni->length / |
317 | 300 | (hand.nand_ps + hand.nand_os); |
318 | | if ((nand_in->length% (hand.nand_ps + hand.nand_os)) !=0) |
| 301 | if ((ni->length% (hand.nand_ps + hand.nand_os)) !=0) |
319 | 302 | page_num++; |
320 | 303 | } |
321 | | temp = ((nand_in->option << 12) & 0xf000) + |
| 304 | temp = ((ni->option << 12) & 0xf000) + |
322 | 305 | ((i<<4) & 0xff0) + NAND_PROGRAM; |
323 | | if (usb_send_data_address_to_ingenic(&ingenic_dev, nand_in->start) != 1) |
| 306 | if (usb_send_data_address_to_ingenic(&ingenic_dev, ni->start) != 1) |
324 | 307 | goto err; |
325 | 308 | if (usb_send_data_length_to_ingenic(&ingenic_dev, page_num) != 1) |
326 | 309 | goto err; |
... | ... | |
330 | 313 | goto err; |
331 | 314 | |
332 | 315 | printf(" Finish! (len %d start_page %d page_num %d)\n", |
333 | | nand_in->length, nand_in->start, page_num); |
| 316 | ni->length, ni->start, page_num); |
334 | 317 | |
335 | 318 | /* Read back to check! */ |
336 | | usb_send_data_address_to_ingenic(&ingenic_dev, nand_in->start); |
| 319 | usb_send_data_address_to_ingenic(&ingenic_dev, ni->start); |
337 | 320 | usb_send_data_length_to_ingenic(&ingenic_dev, page_num); |
338 | 321 | |
339 | | switch (nand_in->option) { |
| 322 | switch (ni->option) { |
340 | 323 | case OOB_ECC: |
341 | 324 | temp = ((OOB_ECC << 12) & 0xf000) + |
342 | 325 | ((i << 4) & 0xff0) + NAND_READ; |
... | ... | |
348 | 331 | start_addr = page_num * (hand.nand_ps + hand.nand_os); |
349 | 332 | break; |
350 | 333 | case NO_OOB: |
| 334 | default: |
351 | 335 | temp = ((NO_OOB << 12) & 0xf000) + |
352 | 336 | ((i << 4) & 0xff0) + NAND_READ; |
353 | 337 | start_addr = page_num * hand.nand_ps; |
354 | 338 | break; |
355 | | default: |
356 | | ; |
357 | 339 | } |
358 | 340 | |
359 | | printf(" Checking %d bytes...", nand_in->length); |
| 341 | printf(" Checking %d bytes...", ni->length); |
360 | 342 | usb_ingenic_nand_ops(&ingenic_dev, temp); |
361 | 343 | usb_read_data_from_ingenic(&ingenic_dev, check_buf, start_addr); |
362 | 344 | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
... | ... | |
364 | 346 | cur_page = (ret[3] << 24) | (ret[2] << 16) | (ret[1] << 8) | |
365 | 347 | (ret[0] << 0); |
366 | 348 | |
367 | | if (nand_in->start == 0 && hand.nand_ps == 4096 && |
| 349 | if (ni->start == 0 && hand.nand_ps == 4096 && |
368 | 350 | hand.fw_args.cpu_id == 0x4740) { |
369 | 351 | printf(" No check! end at page: %d\n", cur_page); |
370 | 352 | fflush(NULL); |
371 | 353 | continue; |
372 | 354 | } |
373 | 355 | |
374 | | if (!nand_in->check(nand_in->buf, check_buf, nand_in->length)) { |
| 356 | if (!ni->check(ni->buf, check_buf, ni->length)) { |
375 | 357 | struct nand_in bad; |
376 | | // tbd: doesn't the other side skip bad blocks too? Can we just deduct 1 from cur_page? |
377 | | // tbd: why do we only mark a block as bad if the last page in the block was written? |
| 358 | /* |
| 359 | * tbd: doesn't the other side skip bad blocks too? Can we just deduct 1 from cur_page? |
| 360 | * tbd: why do we only mark a block as bad if the last page in the block was written? |
| 361 | */ |
378 | 362 | bad.start = (cur_page - 1) / hand.nand_ppb; |
379 | 363 | if (cur_page % hand.nand_ppb == 0) |
380 | 364 | nand_markbad(&bad); |
... | ... | |
391 | 375 | return status; |
392 | 376 | } |
393 | 377 | |
394 | | int nand_erase(struct nand_in *nand_in) |
| 378 | int nand_erase(struct nand_in *ni) |
395 | 379 | { |
396 | 380 | unsigned int start_blk, blk_num, end_block; |
| 381 | unsigned short temp; |
| 382 | int cpu; |
397 | 383 | int i; |
398 | 384 | |
399 | | start_blk = nand_in->start; |
400 | | blk_num = nand_in->length; |
| 385 | start_blk = ni->start; |
| 386 | blk_num = ni->length; |
401 | 387 | if (start_blk > (unsigned int)NAND_MAX_BLK_NUM) { |
402 | 388 | printf(" Start block number overflow!\n"); |
403 | 389 | return -1; |
... | ... | |
407 | 393 | return -1; |
408 | 394 | } |
409 | 395 | |
410 | | int cpu = get_ingenic_cpu(); |
| 396 | cpu = get_ingenic_cpu(); |
411 | 397 | if (cpu != BOOT4740 && cpu != BOOT4750 && cpu != BOOT4760) { |
412 | 398 | printf(" Device unboot! boot it first!\n"); |
413 | 399 | return -1; |
414 | 400 | } |
415 | 401 | |
416 | | for (i = 0; i < nand_in->max_chip; i++) { |
417 | | if ((nand_in->cs_map)[i]==0) |
| 402 | for (i = 0; i < ni->max_chip; i++) { |
| 403 | if ((ni->cs_map)[i]==0) |
418 | 404 | continue; |
419 | 405 | printf(" Erasing No.%d device No.%d flash (start_blk %u blk_num %u)......\n", |
420 | | nand_in->dev, i, start_blk, blk_num); |
| 406 | ni->dev, i, start_blk, blk_num); |
421 | 407 | |
422 | 408 | usb_send_data_address_to_ingenic(&ingenic_dev, start_blk); |
423 | 409 | usb_send_data_length_to_ingenic(&ingenic_dev, blk_num); |
424 | 410 | |
425 | | unsigned short temp = ((i << 4) & 0xff0) + NAND_ERASE; |
| 411 | temp = ((i << 4) & 0xff0) + NAND_ERASE; |
426 | 412 | usb_ingenic_nand_ops(&ingenic_dev, temp); |
427 | 413 | |
428 | 414 | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
... | ... | |
446 | 432 | return 1; |
447 | 433 | } |
448 | 434 | |
449 | | int nand_program_file(struct nand_in *nand_in, char *fname) |
| 435 | int nand_program_file(struct nand_in *ni, char *fname) |
450 | 436 | { |
451 | 437 | |
452 | 438 | int flen, m, j, k; |
453 | | unsigned int start_page = 0, page_num, code_len, offset, transfer_size; |
| 439 | unsigned int start_page = 0, code_len, offset, transfer_size; |
454 | 440 | int fd, status; |
455 | | struct stat fstat; |
| 441 | struct stat fst; |
456 | 442 | struct nand_in n_in; |
457 | 443 | |
458 | | status = stat(fname, &fstat); |
| 444 | status = stat(fname, &fst); |
459 | 445 | |
460 | 446 | if (status < 0) { |
461 | 447 | fprintf(stderr, "Error - can't get file size from '%s': %s\n", |
462 | 448 | fname, strerror(errno)); |
463 | 449 | return -1; |
464 | 450 | } |
465 | | flen = fstat.st_size; |
| 451 | flen = fst.st_size; |
466 | 452 | |
467 | 453 | fd = open(fname, O_RDONLY); |
468 | 454 | if (fd < 0) { |
... | ... | |
471 | 457 | return -1; |
472 | 458 | } |
473 | 459 | |
474 | | printf(" Programing No.%d device, flen %d, start page %d...\n",nand_in->dev, flen, nand_in->start); |
475 | | n_in.start = nand_in->start / hand.nand_ppb; |
476 | | if (nand_in->option == NO_OOB) { |
| 460 | printf(" Programing No.%d device, flen %d, start page %d...\n",ni->dev, flen, ni->start); |
| 461 | n_in.start = ni->start / hand.nand_ppb; |
| 462 | if (ni->option == NO_OOB) { |
477 | 463 | if (flen % (hand.nand_ppb * hand.nand_ps) == 0) |
478 | 464 | n_in.length = flen / (hand.nand_ps * hand.nand_ppb); |
479 | 465 | else |
... | ... | |
487 | 473 | ((hand.nand_ps + hand.nand_os) * hand.nand_ppb) |
488 | 474 | + 1; |
489 | 475 | } |
490 | | n_in.cs_map = nand_in->cs_map; |
491 | | n_in.dev = nand_in->dev; |
492 | | n_in.max_chip = nand_in->max_chip; |
| 476 | n_in.cs_map = ni->cs_map; |
| 477 | n_in.dev = ni->dev; |
| 478 | n_in.max_chip = ni->max_chip; |
493 | 479 | if (nand_erase(&n_in) != 1) |
494 | 480 | return -1; |
495 | | if (nand_in->option == NO_OOB) |
| 481 | if (ni->option == NO_OOB) |
496 | 482 | transfer_size = (hand.nand_ppb * hand.nand_ps); |
497 | 483 | else |
498 | 484 | transfer_size = (hand.nand_ppb * (hand.nand_ps + hand.nand_os)); |
... | ... | |
500 | 486 | m = flen / transfer_size; |
501 | 487 | j = flen % transfer_size; |
502 | 488 | printf(" Size to send %d, transfer_size %d\n", flen, transfer_size); |
503 | | printf(" Image type : %s\n", IMAGE_TYPE[nand_in->option]); |
| 489 | printf(" Image type : %s\n", IMAGE_TYPE[ni->option]); |
504 | 490 | printf(" It will cause %d times buffer transfer.\n", j == 0 ? m : m + 1); |
505 | 491 | fflush(NULL); |
506 | 492 | |
507 | 493 | offset = 0; |
508 | 494 | for (k = 0; k < m; k++) { |
509 | | if (nand_in->option == NO_OOB) |
510 | | page_num = transfer_size / hand.nand_ps; |
511 | | else |
512 | | page_num = transfer_size / (hand.nand_ps + hand.nand_os); |
513 | | |
514 | 495 | code_len = transfer_size; |
515 | 496 | status = read(fd, code_buf, code_len); |
516 | 497 | if (status < code_len) { |
... | ... | |
519 | 500 | return -1; |
520 | 501 | } |
521 | 502 | |
522 | | nand_in->length = code_len; /* code length,not page number! */ |
523 | | nand_in->buf = code_buf; |
524 | | if (nand_program_check(nand_in, &start_page) == -1) |
| 503 | ni->length = code_len; /* code length,not page number! */ |
| 504 | ni->buf = code_buf; |
| 505 | if (nand_program_check(ni, &start_page) == -1) |
525 | 506 | return -1; |
526 | 507 | |
527 | | if (start_page - nand_in->start > hand.nand_ppb) |
| 508 | if (start_page - ni->start > hand.nand_ppb) |
528 | 509 | printf(" Info - skip bad block!\n"); |
529 | | nand_in->start = start_page; |
| 510 | ni->start = start_page; |
530 | 511 | |
531 | 512 | offset += code_len ; |
532 | 513 | } |
... | ... | |
545 | 526 | return -1; |
546 | 527 | } |
547 | 528 | |
548 | | nand_in->length = j; |
549 | | nand_in->buf = code_buf; |
550 | | if (nand_program_check(nand_in, &start_page) == -1) |
| 529 | ni->length = j; |
| 530 | ni->buf = code_buf; |
| 531 | if (nand_program_check(ni, &start_page) == -1) |
551 | 532 | return -1; |
552 | 533 | |
553 | | if (start_page - nand_in->start > hand.nand_ppb) |
| 534 | if (start_page - ni->start > hand.nand_ppb) |
554 | 535 | printf(" Info - skip bad block!"); |
555 | 536 | |
556 | 537 | } |
... | ... | |
559 | 540 | return 1; |
560 | 541 | } |
561 | 542 | |
562 | | int nand_program_file_planes(struct nand_in *nand_in, char *fname) |
563 | | { |
564 | | printf(" not implement yet !\n"); |
565 | | return -1; |
566 | | } |
567 | | |
568 | 543 | int init_nand_in(void) |
569 | 544 | { |
570 | 545 | nand_in.buf = code_buf; |
... | ... | |
612 | 587 | else |
613 | 588 | printf("%s", help); |
614 | 589 | |
615 | | if (hand.nand_plane > 1) |
616 | | nand_program_file_planes(&nand_in, image_file); |
617 | | else |
| 590 | if (hand.nand_plane == 1) |
618 | 591 | nand_program_file(&nand_in, image_file); |
619 | 592 | |
620 | 593 | status = 1; |
621 | | err: |
| 594 | |
622 | 595 | return status; |
623 | 596 | } |
624 | 597 | |
625 | 598 | int nand_query(void) |
626 | 599 | { |
627 | | int i; |
| 600 | int cpu, i; |
628 | 601 | unsigned char csn; |
| 602 | unsigned short ops; |
629 | 603 | |
630 | 604 | if (com_argc < 3) { |
631 | 605 | printf(" Usage: nquery (1) (2)\n" |
... | ... | |
645 | 619 | if (i >= nand_in.max_chip) |
646 | 620 | return -1; |
647 | 621 | |
648 | | int cpu = get_ingenic_cpu(); |
| 622 | cpu = get_ingenic_cpu(); |
649 | 623 | if (cpu != BOOT4740 && cpu != BOOT4750 && cpu != BOOT4760) { |
650 | 624 | printf(" Device unboot! boot it first!\n"); |
651 | 625 | return -1; |
... | ... | |
654 | 628 | csn = i; |
655 | 629 | printf(" ID of No.%d device No.%d flash: \n", nand_in.dev, csn); |
656 | 630 | |
657 | | unsigned short ops = ((csn << 4) & 0xff0) + NAND_QUERY; |
| 631 | ops = ((csn << 4) & 0xff0) + NAND_QUERY; |
658 | 632 | usb_ingenic_nand_ops(&ingenic_dev, ops); |
659 | 633 | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
660 | 634 | printf(" Vendor ID :0x%x \n",(unsigned char)ret[0]); |
... | ... | |
670 | 644 | |
671 | 645 | int nand_read(int mode) |
672 | 646 | { |
673 | | unsigned int i, j, cpu; |
| 647 | unsigned int cpu, j; |
674 | 648 | unsigned int start_addr, length, page_num; |
675 | 649 | unsigned char csn; |
676 | 650 | unsigned short temp = 0; |
... | ... | |
752 | 726 | return 1; |
753 | 727 | } |
754 | 728 | |
755 | | int debug_memory(int obj, unsigned int start, unsigned int size) |
| 729 | int debug_memory(unsigned int start, unsigned int size) |
756 | 730 | { |
757 | 731 | unsigned int buffer[8],tmp; |
758 | 732 | |
... | ... | |
790 | 764 | return -1; |
791 | 765 | |
792 | 766 | usleep(100); |
793 | | usb_read_data_from_ingenic(&ingenic_dev, buffer, 8); |
| 767 | usb_read_data_from_ingenic(&ingenic_dev, (unsigned char *)buffer, 8); |
794 | 768 | if (buffer[0] != 0) |
795 | 769 | printf(" Test memory fail! Last error address is 0x%x !\n", |
796 | 770 | buffer[0]); |
... | ... | |
800 | 774 | return 1; |
801 | 775 | } |
802 | 776 | |
803 | | int debug_gpio(int obj, unsigned char ops, unsigned char pin) |
| 777 | int debug_gpio(unsigned char ops, unsigned char pin) |
804 | 778 | { |
805 | 779 | unsigned int tmp; |
806 | 780 | |
... | ... | |
847 | 821 | |
848 | 822 | int debug_go(void) |
849 | 823 | { |
850 | | unsigned int addr,obj; |
| 824 | unsigned int addr, obj; |
851 | 825 | if (com_argc<3) { |
852 | 826 | printf(" Usage: go (1) (2) \n" |
853 | 827 | " 1:start SDRAM address\n" |
... | ... | |
866 | 840 | return 1; |
867 | 841 | } |
868 | 842 | |
869 | | int sdram_load(struct sdram_in *sdram_in) |
| 843 | int sdram_load(struct sdram_in *si) |
870 | 844 | { |
871 | 845 | int cpu = get_ingenic_cpu(); |
872 | 846 | if (cpu != BOOT4740 && cpu != BOOT4750 && cpu != BOOT4760) { |
... | ... | |
874 | 848 | return -1; |
875 | 849 | } |
876 | 850 | |
877 | | if (sdram_in->length > (unsigned int) MAX_LOAD_SIZE) { |
| 851 | if (si->length > (unsigned int) MAX_LOAD_SIZE) { |
878 | 852 | printf(" Image length too long!\n"); |
879 | 853 | return -1; |
880 | 854 | } |
881 | 855 | |
882 | | ingenic_dev.file_buff = sdram_in->buf; |
883 | | ingenic_dev.file_len = sdram_in->length; |
| 856 | ingenic_dev.file_buff = si->buf; |
| 857 | ingenic_dev.file_len = si->length; |
884 | 858 | usb_send_data_to_ingenic(&ingenic_dev); |
885 | | usb_send_data_address_to_ingenic(&ingenic_dev, sdram_in->start); |
886 | | usb_send_data_length_to_ingenic(&ingenic_dev, sdram_in->length); |
887 | | usb_ingenic_sdram_ops(&ingenic_dev, sdram_in); |
| 859 | usb_send_data_address_to_ingenic(&ingenic_dev, si->start); |
| 860 | usb_send_data_length_to_ingenic(&ingenic_dev, si->length); |
| 861 | usb_ingenic_sdram_ops(&ingenic_dev, SDRAM_LOAD); |
888 | 862 | |
889 | 863 | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
890 | 864 | printf(" Load last address at 0x%x\n", |
... | ... | |
893 | 867 | return 1; |
894 | 868 | } |
895 | 869 | |
896 | | int sdram_load_file(struct sdram_in *sdram_in, char *file_path) |
| 870 | int sdram_load_file(struct sdram_in *si, char *file_path) |
897 | 871 | { |
898 | | struct stat fstat; |
899 | | unsigned int flen,m,j,offset,k; |
| 872 | struct stat fst; |
| 873 | unsigned int flen, m, j, k; |
900 | 874 | int fd, status, res = -1; |
901 | 875 | |
902 | | status = stat(file_path, &fstat); |
| 876 | status = stat(file_path, &fst); |
903 | 877 | if (status < 0) { |
904 | 878 | fprintf(stderr, "Error - can't get file size from '%s': %s\n", |
905 | 879 | file_path, strerror(errno)); |
906 | 880 | goto out; |
907 | 881 | } |
908 | | flen = fstat.st_size; |
| 882 | flen = fst.st_size; |
909 | 883 | |
910 | 884 | fd = open(file_path, O_RDONLY); |
911 | 885 | if (fd < 0) { |
... | ... | |
916 | 890 | |
917 | 891 | m = flen / MAX_LOAD_SIZE; |
918 | 892 | j = flen % MAX_LOAD_SIZE; |
919 | | offset = 0; |
920 | 893 | |
921 | 894 | printf(" Total size to send in byte is :%d\n", flen); |
922 | 895 | printf(" Loading data to SDRAM :\n"); |
923 | 896 | |
924 | 897 | for (k = 0; k < m; k++) { |
925 | | status = read(fd, sdram_in->buf, MAX_LOAD_SIZE); |
| 898 | status = read(fd, si->buf, MAX_LOAD_SIZE); |
926 | 899 | if (status < MAX_LOAD_SIZE) { |
927 | 900 | fprintf(stderr, "Error - can't read file '%s': %s\n", |
928 | 901 | file_path, strerror(errno)); |
929 | 902 | goto close; |
930 | 903 | } |
931 | 904 | |
932 | | sdram_in->length = MAX_LOAD_SIZE; |
933 | | if (sdram_load(sdram_in) < 1) |
| 905 | si->length = MAX_LOAD_SIZE; |
| 906 | if (sdram_load(si) < 1) |
934 | 907 | goto close; |
935 | 908 | |
936 | | sdram_in->start += MAX_LOAD_SIZE; |
| 909 | si->start += MAX_LOAD_SIZE; |
937 | 910 | if ( k % 60 == 0) |
938 | | printf(" 0x%x \n", sdram_in->start); |
| 911 | printf(" 0x%x \n", si->start); |
939 | 912 | } |
940 | 913 | |
941 | 914 | if (j) { |
942 | 915 | if (j % 4 !=0) |
943 | 916 | j += 4 - (j % 4); |
944 | | status = read(fd, sdram_in->buf, j); |
| 917 | status = read(fd, si->buf, j); |
945 | 918 | if (status < j) { |
946 | 919 | fprintf(stderr, "Error - can't read file '%s': %s\n", |
947 | 920 | file_path, strerror(errno)); |
948 | 921 | goto close; |
949 | 922 | } |
950 | 923 | |
951 | | sdram_in->length = j; |
952 | | if (sdram_load(sdram_in) < 1) |
| 924 | si->length = j; |
| 925 | if (sdram_load(si) < 1) |
953 | 926 | goto close; |
954 | 927 | } |
955 | 928 | |
usbboot/src/ingenic_cfg.c |
18 | 18 | |
19 | 19 | #include <errno.h> |
20 | 20 | #include <confuse.h> |
21 | | #include <unistd.h> |
| 21 | #include <unistd.h> |
22 | 22 | #include <string.h> |
23 | 23 | #include "ingenic_cfg.h" |
24 | 24 | #include "usb_boot_defines.h" |
25 | 25 | |
26 | 26 | extern unsigned int total_size; |
27 | 27 | |
28 | | int check_dump_cfg(struct hand *hand) |
| 28 | int check_dump_cfg(struct hand *h) |
29 | 29 | { |
30 | 30 | printf("Now checking whether all configure args valid:"); |
31 | 31 | /* check PLL */ |
32 | | if (hand->fw_args.ext_clk > 27 || hand->fw_args.ext_clk < 12) { |
| 32 | if (h->fw_args.ext_clk > 27 || h->fw_args.ext_clk < 12) { |
33 | 33 | printf(" EXTCLK setting invalid!\n"); |
34 | 34 | return 0; |
35 | 35 | } |
36 | | if (hand->fw_args.phm_div > 32 || hand->fw_args.ext_clk < 2) { |
| 36 | if (h->fw_args.phm_div > 32 || h->fw_args.ext_clk < 2) { |
37 | 37 | printf(" PHMDIV setting invalid!\n"); |
38 | 38 | return 0; |
39 | 39 | } |
40 | | if ((hand->fw_args.cpu_speed * hand->fw_args.ext_clk ) % 12 != 0) { |
| 40 | if ((h->fw_args.cpu_speed * h->fw_args.ext_clk ) % 12 != 0) { |
41 | 41 | printf(" CPUSPEED setting invalid!\n"); |
42 | 42 | return 0; |
43 | 43 | } |
44 | 44 | |
45 | 45 | /* check SDRAM */ |
46 | | if (hand->fw_args.bus_width > 1 ) { |
| 46 | if (h->fw_args.bus_width > 1 ) { |
47 | 47 | printf(" SDRAMWIDTH setting invalid!\n"); |
48 | 48 | return 0; |
49 | 49 | } |
50 | | if (hand->fw_args.bank_num > 1 ) { |
| 50 | if (h->fw_args.bank_num > 1 ) { |
51 | 51 | printf(" BANKNUM setting invalid!\n"); |
52 | 52 | return 0; |
53 | 53 | } |
54 | | if (hand->fw_args.row_addr > 13 && hand->fw_args.row_addr < 11 ) { |
| 54 | if (h->fw_args.row_addr > 13 && h->fw_args.row_addr < 11 ) { |
55 | 55 | printf(" ROWADDR setting invalid!\n"); |
56 | 56 | return 0; |
57 | 57 | } |
58 | | if (hand->fw_args.col_addr > 13 && hand->fw_args.col_addr < 11 ) { |
| 58 | if (h->fw_args.col_addr > 13 && h->fw_args.col_addr < 11 ) { |
59 | 59 | printf(" COLADDR setting invalid!\n"); |
60 | 60 | return 0; |
61 | 61 | } |
62 | 62 | |
63 | 63 | /* check NAND */ |
64 | | if (hand->nand_ps < 2048 && hand->nand_os > 16) { |
| 64 | if (h->nand_ps < 2048 && h->nand_os > 16) { |
65 | 65 | printf(" PAGESIZE or OOBSIZE setting invalid!\n"); |
66 | | printf(" PAGESIZE is %d,\t OOBSIZE is %d\n", |
67 | | hand->nand_ps, hand->nand_os); |
| 66 | printf(" PAGESIZE is %d,\t OOBSIZE is %d\n", |
| 67 | h->nand_ps, h->nand_os); |
68 | 68 | return 0; |
69 | 69 | } |
70 | | if (hand->nand_ps < 2048 && hand->nand_ppb > 32) { |
| 70 | if (h->nand_ps < 2048 && h->nand_ppb > 32) { |
71 | 71 | printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n"); |
72 | 72 | return 0; |
73 | 73 | } |
74 | 74 | |
75 | | if (hand->nand_ps > 512 && hand->nand_os <= 16) { |
| 75 | if (h->nand_ps > 512 && h->nand_os <= 16) { |
76 | 76 | printf(" PAGESIZE or OOBSIZE setting invalid!\n"); |
77 | | printf(" PAGESIZE is %d,\t OOBSIZE is %d\n", |
78 | | hand->nand_ps, hand->nand_os); |
| 77 | printf(" PAGESIZE is %d,\t OOBSIZE is %d\n", |
| 78 | h->nand_ps, h->nand_os); |
79 | 79 | return 0; |
80 | 80 | } |
81 | | if (hand->nand_ps > 512 && hand->nand_ppb < 64) { |
| 81 | if (h->nand_ps > 512 && h->nand_ppb < 64) { |
82 | 82 | printf(" PAGESIZE or PAGEPERBLOCK setting invalid!\n"); |
83 | 83 | return 0; |
84 | 84 | } |
... | ... | |
86 | 86 | |
87 | 87 | printf("Current device setup information:\n"); |
88 | 88 | printf("Crystal work at %dMHz, the CCLK up to %dMHz and PMH_CLK up to %dMHz\n", |
89 | | hand->fw_args.ext_clk, |
90 | | (unsigned int)hand->fw_args.cpu_speed * hand->fw_args.ext_clk, |
91 | | ((unsigned int)hand->fw_args.cpu_speed * hand->fw_args.ext_clk) / hand->fw_args.phm_div); |
| 89 | h->fw_args.ext_clk, |
| 90 | (unsigned int)h->fw_args.cpu_speed * h->fw_args.ext_clk, |
| 91 | ((unsigned int)h->fw_args.cpu_speed * h->fw_args.ext_clk) / h->fw_args.phm_div); |
92 | 92 | |
93 | 93 | printf("SDRAM Total size is %d MB, work in %d bank and %d bit mode\n", |
94 | | total_size / 0x100000, 2 * (hand->fw_args.bank_num + 1), |
95 | | 16 * (2 - hand->fw_args.bus_width)); |
| 94 | total_size / 0x100000, 2 * (h->fw_args.bank_num + 1), |
| 95 | 16 * (2 - h->fw_args.bus_width)); |
96 | 96 | |
97 | 97 | printf("Nand page per block %d, " |
98 | 98 | "Nand page size %d, " |
... | ... | |
100 | 100 | "bad block offset in OOB %d, " |
101 | 101 | "bad block page %d, " |
102 | 102 | "use %d plane mode\n", |
103 | | hand->nand_ppb, |
104 | | hand->nand_ps, |
105 | | hand->nand_eccpos, |
106 | | hand->nand_bbpos, |
107 | | hand->nand_bbpage, |
108 | | hand->nand_plane); |
| 103 | h->nand_ppb, |
| 104 | h->nand_ps, |
| 105 | h->nand_eccpos, |
| 106 | h->nand_bbpos, |
| 107 | h->nand_bbpage, |
| 108 | h->nand_plane); |
109 | 109 | return 1; |
110 | 110 | } |
111 | 111 | |
112 | | int parse_configure(struct hand *hand, char * file_path) |
| 112 | int parse_configure(struct hand *h, char * file_path) |
113 | 113 | { |
114 | | if (access(file_path, F_OK)) { |
115 | | fprintf(stderr, "Error - can't read configure file %s.\n", |
116 | | file_path); |
117 | | return -1; |
118 | | } |
119 | | |
| 114 | cfg_t *cfg; |
120 | 115 | cfg_opt_t opts[] = { |
121 | 116 | CFG_INT("BOUDRATE", 57600, CFGF_NONE), |
122 | 117 | CFG_INT("EXTCLK", 0, CFGF_NONE), |
... | ... | |
153 | 148 | CFG_END() |
154 | 149 | }; |
155 | 150 | |
156 | | cfg_t *cfg; |
| 151 | if (access(file_path, F_OK)) { |
| 152 | fprintf(stderr, "Error - can't read configure file %s.\n", |
| 153 | file_path); |
| 154 | return -1; |
| 155 | } |
| 156 | |
157 | 157 | cfg = cfg_init(opts, 0); |
158 | 158 | if (cfg_parse(cfg, file_path) == CFG_PARSE_ERROR) |
159 | 159 | return -1; |
160 | 160 | |
161 | | hand->fw_args.boudrate = cfg_getint(cfg, "BOUDRATE"); |
162 | | hand->fw_args.ext_clk = cfg_getint(cfg, "EXTCLK"); |
163 | | hand->fw_args.cpu_speed = cfg_getint(cfg, "CPUSPEED"); |
164 | | hand->fw_args.phm_div = cfg_getint(cfg, "PHMDIV"); |
165 | | hand->fw_args.use_uart = cfg_getint(cfg, "USEUART"); |
166 | | |
167 | | hand->fw_args.bus_width = cfg_getint(cfg, "BUSWIDTH"); |
168 | | hand->fw_args.bank_num = cfg_getint(cfg, "BANKS"); |
169 | | hand->fw_args.row_addr = cfg_getint(cfg, "ROWADDR"); |
170 | | hand->fw_args.col_addr = cfg_getint(cfg, "COLADDR"); |
171 | | |
172 | | hand->fw_args.is_mobile = cfg_getint(cfg, "ISMOBILE"); |
173 | | hand->fw_args.is_busshare = cfg_getint(cfg, "ISBUSSHARE"); |
174 | | hand->fw_args.debug_ops = cfg_getint(cfg, "DEBUGOPS"); |
175 | | hand->fw_args.pin_num = cfg_getint(cfg, "PINNUM"); |
176 | | hand->fw_args.start = cfg_getint(cfg, "START"); |
177 | | hand->fw_args.size = cfg_getint(cfg, "SIZE"); |
178 | | |
179 | | hand->nand_bw = cfg_getint(cfg, "NAND_BUSWIDTH"); |
180 | | hand->nand_rc = cfg_getint(cfg, "NAND_ROWCYCLES"); |
181 | | hand->nand_ps = cfg_getint(cfg, "NAND_PAGESIZE"); |
182 | | hand->nand_ppb = cfg_getint(cfg, "NAND_PAGEPERBLOCK"); |
183 | | hand->nand_force_erase = cfg_getint(cfg, "NAND_FORCEERASE"); |
184 | | hand->nand_os = cfg_getint(cfg, "NAND_OOBSIZE"); |
185 | | hand->nand_eccpos = cfg_getint(cfg, "NAND_ECCPOS"); |
186 | | hand->nand_bbpos = cfg_getint(cfg, "NAND_BADBLOCKPOS"); |
187 | | hand->nand_bbpage = cfg_getint(cfg, "NAND_BADBLOCKPAGE"); |
188 | | hand->nand_plane = cfg_getint(cfg, "NAND_PLANENUM"); |
189 | | hand->nand_bchbit = cfg_getint(cfg, "NAND_BCHBIT"); |
190 | | hand->nand_wppin = cfg_getint(cfg, "NAND_WPPIN"); |
191 | | hand->nand_bpc = cfg_getint(cfg, "NAND_BLOCKPERCHIP"); |
| 161 | h->fw_args.boudrate = cfg_getint(cfg, "BOUDRATE"); |
| 162 | h->fw_args.ext_clk = cfg_getint(cfg, "EXTCLK"); |
| 163 | h->fw_args.cpu_speed = cfg_getint(cfg, "CPUSPEED"); |
| 164 | h->fw_args.phm_div = cfg_getint(cfg, "PHMDIV"); |
| 165 | h->fw_args.use_uart = cfg_getint(cfg, "USEUART"); |
| 166 | |
| 167 | h->fw_args.bus_width = cfg_getint(cfg, "BUSWIDTH"); |
| 168 | h->fw_args.bank_num = cfg_getint(cfg, "BANKS"); |
| 169 | h->fw_args.row_addr = cfg_getint(cfg, "ROWADDR"); |
| 170 | h->fw_args.col_addr = cfg_getint(cfg, "COLADDR"); |
| 171 | |
| 172 | h->fw_args.is_mobile = cfg_getint(cfg, "ISMOBILE"); |
| 173 | h->fw_args.is_busshare = cfg_getint(cfg, "ISBUSSHARE"); |
| 174 | h->fw_args.debug_ops = cfg_getint(cfg, "DEBUGOPS"); |
| 175 | h->fw_args.pin_num = cfg_getint(cfg, "PINNUM"); |
| 176 | h->fw_args.start = cfg_getint(cfg, "START"); |
| 177 | h->fw_args.size = cfg_getint(cfg, "SIZE"); |
| 178 | |
| 179 | h->nand_bw = cfg_getint(cfg, "NAND_BUSWIDTH"); |
| 180 | h->nand_rc = cfg_getint(cfg, "NAND_ROWCYCLES"); |
| 181 | h->nand_ps = cfg_getint(cfg, "NAND_PAGESIZE"); |
| 182 | h->nand_ppb = cfg_getint(cfg, "NAND_PAGEPERBLOCK"); |
| 183 | h->nand_force_erase = cfg_getint(cfg, "NAND_FORCEERASE"); |
| 184 | h->nand_os = cfg_getint(cfg, "NAND_OOBSIZE"); |
| 185 | h->nand_eccpos = cfg_getint(cfg, "NAND_ECCPOS"); |
| 186 | h->nand_bbpos = cfg_getint(cfg, "NAND_BADBLOCKPOS"); |
| 187 | h->nand_bbpage = cfg_getint(cfg, "NAND_BADBLOCKPAGE"); |
| 188 | h->nand_plane = cfg_getint(cfg, "NAND_PLANENUM"); |
| 189 | h->nand_bchbit = cfg_getint(cfg, "NAND_BCHBIT"); |
| 190 | h->nand_wppin = cfg_getint(cfg, "NAND_WPPIN"); |
| 191 | h->nand_bpc = cfg_getint(cfg, "NAND_BLOCKPERCHIP"); |
192 | 192 | |
193 | 193 | cfg_free(cfg); |
194 | 194 | |
195 | | if (hand->fw_args.bus_width == 32) |
196 | | hand->fw_args.bus_width = 0; |
| 195 | if (h->fw_args.bus_width == 32) |
| 196 | h->fw_args.bus_width = 0; |
197 | 197 | else |
198 | | hand->fw_args.bus_width = 1; |
199 | | hand->fw_args.bank_num = hand->fw_args.bank_num / 4; |
200 | | hand->fw_args.cpu_speed = hand->fw_args.cpu_speed / hand->fw_args.ext_clk; |
201 | | |
| 198 | h->fw_args.bus_width = 1; |
| 199 | h->fw_args.bank_num = h->fw_args.bank_num / 4; |
| 200 | h->fw_args.cpu_speed = h->fw_args.cpu_speed / h->fw_args.ext_clk; |
| 201 | |
202 | 202 | total_size = (unsigned int) |
203 | | (2 << (hand->fw_args.row_addr + hand->fw_args.col_addr - 1)) * 2 |
204 | | * (hand->fw_args.bank_num + 1) * 2 |
205 | | * (2 - hand->fw_args.bus_width); |
| 203 | (2 << (h->fw_args.row_addr + h->fw_args.col_addr - 1)) * 2 |
| 204 | * (h->fw_args.bank_num + 1) * 2 |
| 205 | * (2 - h->fw_args.bus_width); |
206 | 206 | |
207 | | if (check_dump_cfg(hand) < 1) |
| 207 | if (check_dump_cfg(h) < 1) |
208 | 208 | return -1; |
209 | 209 | |
210 | 210 | return 1; |
usbboot/src/ingenic_usb.c |
2 | 2 | * Copyright(C) 2009 Qi Hardware Inc., |
3 | 3 | * Authors: Xiangfu Liu <xiangfu@sharism.cc> |
4 | 4 | * Marek Lindner <lindner_marek@yahoo.de> |
5 | | * |
| 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or modify |
7 | 7 | * it under the terms of the GNU General Public License as published by |
8 | 8 | * the Free Software Foundation, either version 3 of the License, or |
... | ... | |
26 | 26 | |
27 | 27 | extern unsigned int total_size; |
28 | 28 | |
29 | | static int get_ingenic_device(struct ingenic_dev *ingenic_dev) |
| 29 | static int get_ingenic_device(struct ingenic_dev *id) |
30 | 30 | { |
31 | | struct usb_bus *usb_busses, *usb_bus; |
| 31 | struct usb_bus *ub, *usb_bus; |
32 | 32 | struct usb_device *usb_dev; |
33 | 33 | int count = 0; |
34 | 34 | |
35 | | usb_busses = usb_get_busses(); |
| 35 | ub = usb_get_busses(); |
36 | 36 | |
37 | | for (usb_bus = usb_busses; usb_bus != NULL; usb_bus = usb_bus->next) { |
38 | | for (usb_dev = usb_bus->devices; usb_dev != NULL; |
| 37 | for (usb_bus = ub; usb_bus != NULL; usb_bus = usb_bus->next) { |
| 38 | for (usb_dev = usb_bus->devices; usb_dev != NULL; |
39 | 39 | usb_dev = usb_dev->next) { |
40 | 40 | |
41 | 41 | if ((usb_dev->descriptor.idVendor == VENDOR_ID) && |
42 | 42 | (usb_dev->descriptor.idProduct == PRODUCT_ID_4740 || |
43 | 43 | usb_dev->descriptor.idProduct == PRODUCT_ID_4760)) { |
44 | | ingenic_dev->usb_dev = usb_dev; |
| 44 | id->usb_dev = usb_dev; |
45 | 45 | count++; |
46 | 46 | } |
47 | 47 | |
... | ... | |
51 | 51 | return count; |
52 | 52 | } |
53 | 53 | |
54 | | static int get_ingenic_interface(struct ingenic_dev *ingenic_dev) |
| 54 | static int get_ingenic_interface(struct ingenic_dev *id) |
55 | 55 | { |
56 | 56 | struct usb_config_descriptor *usb_config_desc; |
57 | 57 | struct usb_interface_descriptor *usb_if_desc; |
58 | 58 | struct usb_interface *usb_if; |
59 | 59 | int config_index, if_index, alt_index; |
60 | 60 | |
61 | | for (config_index = 0; |
62 | | config_index < ingenic_dev->usb_dev->descriptor.bNumConfigurations; |
| 61 | for (config_index = 0; |
| 62 | config_index < id->usb_dev->descriptor.bNumConfigurations; |
63 | 63 | config_index++) { |
64 | | usb_config_desc = &ingenic_dev->usb_dev->config[config_index]; |
| 64 | usb_config_desc = &id->usb_dev->config[config_index]; |
65 | 65 | |
66 | 66 | if (!usb_config_desc) |
67 | 67 | return 0; |
68 | 68 | |
69 | | for (if_index = 0; if_index < usb_config_desc->bNumInterfaces; |
| 69 | for (if_index = 0; if_index < usb_config_desc->bNumInterfaces; |
70 | 70 | if_index++) { |
71 | 71 | usb_if = &usb_config_desc->interface[if_index]; |
72 | 72 | |
... | ... | |
82 | 82 | |
83 | 83 | if ((usb_if_desc->bInterfaceClass == 0xff) && |
84 | 84 | (usb_if_desc->bInterfaceSubClass == 0)) { |
85 | | ingenic_dev->interface = |
| 85 | id->interface = |
86 | 86 | usb_if_desc->bInterfaceNumber; |
87 | 87 | return 1; |
88 | 88 | } |
... | ... | |
93 | 93 | return 0; |
94 | 94 | } |
95 | 95 | |
96 | | int usb_ingenic_init(struct ingenic_dev *ingenic_dev) |
| 96 | int usb_ingenic_init(struct ingenic_dev *id) |
97 | 97 | { |
98 | 98 | int num_ingenic, status = -1; |
99 | 99 | |
100 | | memset(ingenic_dev, 0, sizeof(struct ingenic_dev)); |
| 100 | memset(id, 0, sizeof(struct ingenic_dev)); |
101 | 101 | |
102 | 102 | usb_init(); |
103 | 103 | /* usb_set_debug(255); */ |
104 | 104 | usb_find_busses(); |
105 | 105 | usb_find_devices(); |
106 | 106 | |
107 | | num_ingenic = get_ingenic_device(ingenic_dev); |
| 107 | num_ingenic = get_ingenic_device(id); |
108 | 108 | |
109 | 109 | if (num_ingenic == 0) { |
110 | 110 | fprintf(stderr, "Error - no XBurst device found\n"); |
... | ... | |
117 | 117 | goto out; |
118 | 118 | } |
119 | 119 | |
120 | | ingenic_dev->usb_handle = usb_open(ingenic_dev->usb_dev); |
121 | | if (!ingenic_dev->usb_handle) { |
| 120 | id->usb_handle = usb_open(id->usb_dev); |
| 121 | if (!id->usb_handle) { |
122 | 122 | fprintf(stderr, "Error - can't open XBurst device: %s\n", |
123 | 123 | usb_strerror()); |
124 | 124 | goto out; |
125 | 125 | } |
126 | 126 | |
127 | | if (get_ingenic_interface(ingenic_dev) < 1) { |
| 127 | if (get_ingenic_interface(id) < 1) { |
128 | 128 | fprintf(stderr, "Error - can't find XBurst interface\n"); |
129 | 129 | goto out; |
130 | 130 | } |
131 | 131 | |
132 | | if (usb_claim_interface(ingenic_dev->usb_handle, ingenic_dev->interface) |
| 132 | if (usb_claim_interface(id->usb_handle, id->interface) |
133 | 133 | < 0) { |
134 | 134 | fprintf(stderr, "Error - can't claim XBurst interface: %s\n", |
135 | 135 | usb_strerror()); |
... | ... | |
142 | 142 | return status; |
143 | 143 | } |
144 | 144 | |
145 | | int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev) |
| 145 | int usb_get_ingenic_cpu(struct ingenic_dev *id) |
146 | 146 | { |
147 | 147 | int status; |
148 | 148 | |
149 | | memset(&ingenic_dev->cpu_info_buff, 0, |
150 | | ARRAY_SIZE(ingenic_dev->cpu_info_buff)); |
| 149 | memset(&id->cpu_info_buff, 0, |
| 150 | ARRAY_SIZE(id->cpu_info_buff)); |
151 | 151 | |
152 | 152 | sleep(1); |
153 | | status = usb_control_msg(ingenic_dev->usb_handle, |
154 | | /* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR |USB_RECIP_DEVICE, |
155 | | /* bRequest */ VR_GET_CPU_INFO, |
156 | | /* wValue */ 0, |
157 | | /* wIndex */ 0, |
158 | | /* Data */ ingenic_dev->cpu_info_buff, |
159 | | /* wLength */ 8, |
160 | | USB_TIMEOUT); |
161 | | |
162 | | if (status != sizeof(ingenic_dev->cpu_info_buff) - 1 ) { |
| 153 | status = usb_control_msg(id->usb_handle, |
| 154 | /* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR |USB_RECIP_DEVICE, |
| 155 | /* bRequest */ VR_GET_CPU_INFO, |
| 156 | /* wValue */ 0, |
| 157 | /* wIndex */ 0, |
| 158 | /* Data */ id->cpu_info_buff, |
| 159 | /* wLength */ 8, |
| 160 | USB_TIMEOUT); |
| 161 | |
| 162 | if (status != sizeof(id->cpu_info_buff) - 1 ) { |
163 | 163 | fprintf(stderr, "Error - " |
164 | 164 | "can't retrieve XBurst CPU information: %i\n", status); |
165 | 165 | return status; |
166 | 166 | } |
167 | 167 | |
168 | | ingenic_dev->cpu_info_buff[8] = '\0'; |
169 | | printf(" CPU data: %s\n", ingenic_dev->cpu_info_buff); |
| 168 | id->cpu_info_buff[8] = '\0'; |
| 169 | printf(" CPU data: %s\n", id->cpu_info_buff); |
170 | 170 | |
171 | | if (!strcmp(ingenic_dev->cpu_info_buff,"JZ4740V1")) return JZ4740V1; |
172 | | if (!strcmp(ingenic_dev->cpu_info_buff,"JZ4750V1")) return JZ4750V1; |
173 | | if (!strcmp(ingenic_dev->cpu_info_buff,"JZ4760V1")) return JZ4760V1; |
174 | | if (!strcmp(ingenic_dev->cpu_info_buff,"Boot4740")) return BOOT4740; |
175 | | if (!strcmp(ingenic_dev->cpu_info_buff,"Boot4750")) return BOOT4750; |
176 | | if (!strcmp(ingenic_dev->cpu_info_buff,"Boot4760")) return BOOT4760; |
| 171 | if (!strcmp(id->cpu_info_buff,"JZ4740V1")) return JZ4740V1; |
| 172 | if (!strcmp(id->cpu_info_buff,"JZ4750V1")) return JZ4750V1; |
| 173 | if (!strcmp(id->cpu_info_buff,"JZ4760V1")) return JZ4760V1; |
| 174 | if (!strcmp(id->cpu_info_buff,"Boot4740")) return BOOT4740; |
| 175 | if (!strcmp(id->cpu_info_buff,"Boot4750")) return BOOT4750; |
| 176 | if (!strcmp(id->cpu_info_buff,"Boot4760")) return BOOT4760; |
177 | 177 | |
178 | 178 | return -1; |
179 | 179 | } |
180 | 180 | |
181 | | int usb_ingenic_flush_cache(struct ingenic_dev *ingenic_dev) |
| 181 | int usb_ingenic_flush_cache(struct ingenic_dev *id) |
182 | 182 | { |
183 | 183 | int status; |
184 | 184 | |
185 | | status = usb_control_msg(ingenic_dev->usb_handle, |
186 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
187 | | /* bRequest */ VR_FLUSH_CACHES, |
188 | | /* wValue */ 0, |
189 | | /* wIndex */ 0, |
190 | | /* Data */ 0, |
191 | | /* wLength */ 0, |
192 | | USB_TIMEOUT); |
| 185 | status = usb_control_msg(id->usb_handle, |
| 186 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 187 | /* bRequest */ VR_FLUSH_CACHES, |
| 188 | /* wValue */ 0, |
| 189 | /* wIndex */ 0, |
| 190 | /* Data */ 0, |
| 191 | /* wLength */ 0, |
| 192 | USB_TIMEOUT); |
193 | 193 | |
194 | 194 | if (status != 0) { |
195 | 195 | fprintf(stderr, "Error - can't flush cache: %i\n", status); |
... | ... | |
199 | 199 | return 1; |
200 | 200 | } |
201 | 201 | |
202 | | int usb_send_data_length_to_ingenic(struct ingenic_dev *ingenic_dev, int len) |
| 202 | int usb_send_data_length_to_ingenic(struct ingenic_dev *id, int len) |
203 | 203 | { |
204 | 204 | int status; |
205 | 205 | /* tell the device the length of the file to be uploaded */ |
206 | | status = usb_control_msg(ingenic_dev->usb_handle, |
207 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
208 | | /* bRequest */ VR_SET_DATA_LENGTH, |
209 | | /* wValue */ STAGE_ADDR_MSB(len), |
210 | | /* wIndex */ STAGE_ADDR_LSB(len), |
211 | | /* Data */ 0, |
212 | | /* wLength */ 0, |
213 | | USB_TIMEOUT); |
| 206 | status = usb_control_msg(id->usb_handle, |
| 207 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 208 | /* bRequest */ VR_SET_DATA_LENGTH, |
| 209 | /* wValue */ STAGE_ADDR_MSB(len), |
| 210 | /* wIndex */ STAGE_ADDR_LSB(len), |
| 211 | /* Data */ 0, |
| 212 | /* wLength */ 0, |
| 213 | USB_TIMEOUT); |
214 | 214 | |
215 | 215 | if (status != 0) { |
216 | 216 | fprintf(stderr, "Error - " |
... | ... | |
221 | 221 | return 1; |
222 | 222 | } |
223 | 223 | |
224 | | int usb_send_data_address_to_ingenic(struct ingenic_dev *ingenic_dev, |
| 224 | int usb_send_data_address_to_ingenic(struct ingenic_dev *id, |
225 | 225 | unsigned int stage_addr) |
226 | 226 | { |
227 | 227 | int status; |
228 | 228 | /* tell the device the RAM address to store the file */ |
229 | | status = usb_control_msg(ingenic_dev->usb_handle, |
230 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
231 | | /* bRequest */ VR_SET_DATA_ADDRESS, |
232 | | /* wValue */ STAGE_ADDR_MSB(stage_addr), |
233 | | /* wIndex */ STAGE_ADDR_LSB(stage_addr), |
234 | | /* Data */ 0, |
235 | | /* wLength */ 0, |
236 | | USB_TIMEOUT); |
| 229 | status = usb_control_msg(id->usb_handle, |
| 230 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 231 | /* bRequest */ VR_SET_DATA_ADDRESS, |
| 232 | /* wValue */ STAGE_ADDR_MSB(stage_addr), |
| 233 | /* wIndex */ STAGE_ADDR_LSB(stage_addr), |
| 234 | /* Data */ 0, |
| 235 | /* wLength */ 0, |
| 236 | USB_TIMEOUT); |
237 | 237 | |
238 | 238 | if (status != 0) { |
239 | 239 | fprintf(stderr, "Error - " |
... | ... | |
244 | 244 | return 1; |
245 | 245 | } |
246 | 246 | |
247 | | int usb_send_data_to_ingenic(struct ingenic_dev *ingenic_dev) |
| 247 | int usb_send_data_to_ingenic(struct ingenic_dev *id) |
248 | 248 | { |
249 | 249 | int status; |
250 | | status = usb_bulk_write(ingenic_dev->usb_handle, |
| 250 | status = usb_bulk_write(id->usb_handle, |
251 | 251 | /* endpoint */ INGENIC_OUT_ENDPOINT, |
252 | | /* bulk data */ ingenic_dev->file_buff, |
253 | | /* bulk data length */ ingenic_dev->file_len, |
254 | | USB_TIMEOUT); |
255 | | if (status < (int)ingenic_dev->file_len) { |
| 252 | /* bulk data */ (char *)id->file_buff, |
| 253 | /* bulk data length */ id->file_len, |
| 254 | USB_TIMEOUT); |
| 255 | if (status < (int)id->file_len) { |
256 | 256 | fprintf(stderr, "Error - " |
257 | 257 | "can't send bulk data to Ingenic CPU: %i %s\n", status, usb_strerror()); |
258 | 258 | return -1; |
... | ... | |
261 | 261 | return 1; |
262 | 262 | } |
263 | 263 | |
264 | | int usb_read_data_from_ingenic(struct ingenic_dev *ingenic_dev, |
| 264 | int usb_read_data_from_ingenic(struct ingenic_dev *id, |
265 | 265 | unsigned char *buff, unsigned int len) |
266 | 266 | { |
267 | 267 | int status; |
268 | | status = usb_bulk_read(ingenic_dev->usb_handle, |
269 | | /* endpoint */ INGENIC_IN_ENDPOINT, |
270 | | /* bulk data */ buff, |
| 268 | status = usb_bulk_read(id->usb_handle, |
| 269 | /* endpoint */ INGENIC_IN_ENDPOINT, |
| 270 | /* bulk data */ (char *)buff, |
271 | 271 | /* bulk data length */ len, |
272 | | USB_TIMEOUT); |
| 272 | USB_TIMEOUT); |
273 | 273 | |
274 | 274 | if (status < (int)len) { |
275 | 275 | fprintf(stderr, "Error - " |
... | ... | |
280 | 280 | return 1; |
281 | 281 | } |
282 | 282 | |
283 | | int usb_ingenic_start(struct ingenic_dev *ingenic_dev, int rqst, int stage_addr) |
| 283 | int usb_ingenic_start(struct ingenic_dev *id, int rqst, unsigned int stage_addr) |
284 | 284 | { |
285 | 285 | int status; |
286 | 286 | |
287 | 287 | /* tell the device to start the uploaded device */ |
288 | | status = usb_control_msg(ingenic_dev->usb_handle, |
289 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 288 | status = usb_control_msg(id->usb_handle, |
| 289 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
290 | 290 | /* bRequest */ rqst, |
291 | | /* wValue */ STAGE_ADDR_MSB(stage_addr), |
292 | | /* wIndex */ STAGE_ADDR_LSB(stage_addr), |
293 | | /* Data */ 0, |
294 | | /* wLength */ 0, |
295 | | USB_TIMEOUT); |
| 291 | /* wValue */ STAGE_ADDR_MSB(stage_addr), |
| 292 | /* wIndex */ STAGE_ADDR_LSB(stage_addr), |
| 293 | /* Data */ 0, |
| 294 | /* wLength */ 0, |
| 295 | USB_TIMEOUT); |
296 | 296 | |
297 | 297 | if (status != 0) { |
298 | 298 | fprintf(stderr, "Error - can't start the uploaded binary " |
... | ... | |
302 | 302 | return 1; |
303 | 303 | } |
304 | 304 | |
305 | | int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage) |
| 305 | int usb_ingenic_upload(struct ingenic_dev *id, int stage) |
306 | 306 | { |
307 | | int status; |
308 | | |
| 307 | unsigned int stage_addr; |
309 | 308 | unsigned int stage2_addr; |
310 | | stage2_addr = total_size + 0x80000000; |
311 | | stage2_addr -= CODE_SIZE; |
312 | | |
313 | | unsigned int stage_addr = (stage == 1 ? 0x80002000 : stage2_addr); |
314 | 309 | int rqst = VR_PROGRAM_START1; |
315 | 310 | |
316 | | usb_send_data_address_to_ingenic(ingenic_dev, stage_addr); |
317 | | printf(" Download stage %d program and execute at 0x%08x\n", |
| 311 | stage2_addr = 0x80000000 + total_size - CODE_SIZE; |
| 312 | stage_addr = (stage == 1 ? 0x80002000 : stage2_addr); |
| 313 | |
| 314 | usb_send_data_address_to_ingenic(id, stage_addr); |
| 315 | printf(" Download stage %d program and execute at 0x%08x\n", |
318 | 316 | stage, (stage_addr)); |
319 | | usb_send_data_to_ingenic(ingenic_dev); |
| 317 | usb_send_data_to_ingenic(id); |
320 | 318 | |
321 | 319 | if (stage == 2) { |
322 | | if (usb_get_ingenic_cpu(ingenic_dev) < 1) |
| 320 | if (usb_get_ingenic_cpu(id) < 1) |
323 | 321 | return -1; |
324 | | usb_ingenic_flush_cache(ingenic_dev); |
| 322 | usb_ingenic_flush_cache(id); |
325 | 323 | rqst = VR_PROGRAM_START2; |
326 | 324 | } |
327 | 325 | |
328 | 326 | usleep(100); |
329 | | if (usb_ingenic_start(ingenic_dev, rqst, stage_addr) < 1) |
| 327 | if (usb_ingenic_start(id, rqst, stage_addr) < 1) |
330 | 328 | return -1; |
331 | 329 | usleep(100); |
332 | | if (usb_get_ingenic_cpu(ingenic_dev) < 1) |
| 330 | if (usb_get_ingenic_cpu(id) < 1) |
333 | 331 | return -1; |
334 | 332 | |
335 | 333 | return 1; |
336 | 334 | } |
337 | 335 | |
338 | | void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev) |
| 336 | void usb_ingenic_cleanup(struct ingenic_dev *id) |
339 | 337 | { |
340 | | if ((ingenic_dev->usb_handle) && (ingenic_dev->interface)) |
341 | | usb_release_interface(ingenic_dev->usb_handle, |
342 | | ingenic_dev->interface); |
| 338 | if ((id->usb_handle) && (id->interface)) |
| 339 | usb_release_interface(id->usb_handle, |
| 340 | id->interface); |
343 | 341 | |
344 | | if (ingenic_dev->usb_handle) |
345 | | usb_close(ingenic_dev->usb_handle); |
| 342 | if (id->usb_handle) |
| 343 | usb_close(id->usb_handle); |
346 | 344 | } |
347 | 345 | |
348 | | int usb_ingenic_nand_ops(struct ingenic_dev *ingenic_dev, int ops) |
| 346 | int usb_ingenic_nand_ops(struct ingenic_dev *id, int ops) |
349 | 347 | { |
350 | 348 | int status; |
351 | | status = usb_control_msg(ingenic_dev->usb_handle, |
352 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
353 | | /* bRequest */ VR_NAND_OPS, |
354 | | /* wValue */ ops & 0xffff, |
355 | | /* wIndex */ 0, |
356 | | /* Data */ 0, |
357 | | /* wLength */ 0, |
358 | | USB_TIMEOUT); |
| 349 | status = usb_control_msg(id->usb_handle, |
| 350 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 351 | /* bRequest */ VR_NAND_OPS, |
| 352 | /* wValue */ ops & 0xffff, |
| 353 | /* wIndex */ 0, |
| 354 | /* Data */ 0, |
| 355 | /* wLength */ 0, |
| 356 | USB_TIMEOUT); |
359 | 357 | |
360 | 358 | if (status != 0) { |
361 | 359 | fprintf(stderr, "Error - " |
... | ... | |
366 | 364 | return 1; |
367 | 365 | } |
368 | 366 | |
369 | | int usb_ingenic_configration(struct ingenic_dev *ingenic_dev, int ops) |
| 367 | int usb_ingenic_configration(struct ingenic_dev *id, int ops) |
370 | 368 | { |
371 | 369 | int status; |
372 | | status = usb_control_msg(ingenic_dev->usb_handle, |
373 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
374 | | /* bRequest */ VR_CONFIGRATION, |
375 | | /* wValue */ ops, |
376 | | /* wIndex */ 0, |
377 | | /* Data */ 0, |
378 | | /* wLength */ 0, |
379 | | USB_TIMEOUT); |
| 370 | status = usb_control_msg(id->usb_handle, |
| 371 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 372 | /* bRequest */ VR_CONFIGRATION, |
| 373 | /* wValue */ ops, |
| 374 | /* wIndex */ 0, |
| 375 | /* Data */ 0, |
| 376 | /* wLength */ 0, |
| 377 | USB_TIMEOUT); |
380 | 378 | |
381 | 379 | if (status != 0) { |
382 | 380 | fprintf(stderr, "Error - " |
... | ... | |
387 | 385 | return 1; |
388 | 386 | } |
389 | 387 | |
390 | | int usb_ingenic_sdram_ops(struct ingenic_dev *ingenic_dev, int ops) |
| 388 | int usb_ingenic_sdram_ops(struct ingenic_dev *id, int ops) |
391 | 389 | { |
392 | 390 | int status; |
393 | | status = usb_control_msg(ingenic_dev->usb_handle, |
394 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
395 | | /* bRequest */ VR_SDRAM_OPS, |
396 | | /* wValue */ ops, |
397 | | /* wIndex */ 0, |
398 | | /* Data */ 0, |
399 | | /* wLength */ 0, |
400 | | USB_TIMEOUT); |
| 391 | status = usb_control_msg(id->usb_handle, |
| 392 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 393 | /* bRequest */ VR_SDRAM_OPS, |
| 394 | /* wValue */ ops, |
| 395 | /* wIndex */ 0, |
| 396 | /* Data */ 0, |
| 397 | /* wLength */ 0, |
| 398 | USB_TIMEOUT); |
401 | 399 | |
402 | 400 | if (status != 0) { |
403 | 401 | fprintf(stderr, "Error - " |
... | ... | |
408 | 406 | return 1; |
409 | 407 | } |
410 | 408 | |
411 | | int usb_ingenic_reset(struct ingenic_dev *ingenic_dev, int ops) |
| 409 | int usb_ingenic_reset(struct ingenic_dev *id, int ops) |
412 | 410 | { |
413 | 411 | int status; |
414 | | status = usb_control_msg(ingenic_dev->usb_handle, |
415 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
416 | | /* bRequest */ VR_RESET, |
417 | | /* wValue */ ops, |
418 | | /* wIndex */ 0, |
419 | | /* Data */ 0, |
420 | | /* wLength */ 0, |
421 | | USB_TIMEOUT); |
| 412 | status = usb_control_msg(id->usb_handle, |
| 413 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 414 | /* bRequest */ VR_RESET, |
| 415 | /* wValue */ ops, |
| 416 | /* wIndex */ 0, |
| 417 | /* Data */ 0, |
| 418 | /* wLength */ 0, |
| 419 | USB_TIMEOUT); |
422 | 420 | |
423 | 421 | if (status != 0) { |
424 | 422 | fprintf(stderr, "Error - " |