diff options
Diffstat (limited to 'firmware/target/arm/rk27xx/sd-rk27xx.c')
-rw-r--r-- | firmware/target/arm/rk27xx/sd-rk27xx.c | 125 |
1 files changed, 76 insertions, 49 deletions
diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c index c5a23ad00d..dab6c3e1f3 100644 --- a/firmware/target/arm/rk27xx/sd-rk27xx.c +++ b/firmware/target/arm/rk27xx/sd-rk27xx.c | |||
@@ -457,73 +457,90 @@ int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count, | |||
457 | 457 | ||
458 | ret = 0; | 458 | ret = 0; |
459 | retry = false; /* reset retry flag */ | 459 | retry = false; /* reset retry flag */ |
460 | mmu_buff_reset(); /* reset recive buff state */ | 460 | |
461 | mmu_buff_reset(); | ||
462 | |||
463 | if (cnt == 1) | ||
464 | { | ||
465 | /* last block to tranfer */ | ||
466 | SD_DATAT = DATA_XFER_START | DATA_XFER_READ | | ||
467 | DATA_BUS_1LINE | DATA_XFER_DMA_DIS | | ||
468 | DATA_XFER_SINGLE; | ||
469 | } | ||
470 | else | ||
471 | { | ||
472 | /* more than one block to transfer */ | ||
473 | SD_DATAT = DATA_XFER_START | DATA_XFER_READ | | ||
474 | DATA_BUS_1LINE | DATA_XFER_DMA_DIS | | ||
475 | DATA_XFER_MULTI; | ||
476 | } | ||
461 | 477 | ||
462 | /* issue read command to the card */ | 478 | /* issue read command to the card */ |
463 | if (!send_cmd(SD_READ_MULTIPLE_BLOCK, start, RES_R1, &response)) | 479 | if (!send_cmd(SD_READ_MULTIPLE_BLOCK, start, RES_R1, &response)) |
464 | { | 480 | { |
465 | ret = -4; | 481 | ret = -2; |
466 | continue; | 482 | continue; |
467 | } | 483 | } |
468 | 484 | ||
469 | while (cnt > 0) | 485 | while (cnt > 0) |
470 | { | 486 | { |
471 | if (cnt == 1) | ||
472 | { | ||
473 | /* last block to tranfer */ | ||
474 | SD_DATAT = DATA_XFER_START | DATA_XFER_READ | | ||
475 | DATA_BUS_1LINE | DATA_XFER_DMA_DIS | | ||
476 | DATA_XFER_SINGLE; | ||
477 | } | ||
478 | else | ||
479 | { | ||
480 | /* more than one block to transfer */ | ||
481 | SD_DATAT = DATA_XFER_START | DATA_XFER_READ | | ||
482 | DATA_BUS_1LINE | DATA_XFER_DMA_DIS | | ||
483 | DATA_XFER_MULTI; | ||
484 | } | ||
485 | |||
486 | /* wait for transfer completion */ | 487 | /* wait for transfer completion */ |
487 | semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK); | 488 | semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK); |
488 | 489 | ||
489 | if (retry) | 490 | if (retry) |
490 | { | 491 | { |
491 | /* data transfer error */ | 492 | /* data transfer error */ |
492 | ret = -5; | 493 | ret = -3; |
493 | break; | 494 | break; |
494 | } | 495 | } |
495 | 496 | ||
496 | /* exchange buffers */ | 497 | /* exchange buffers */ |
497 | mmu_switch_buff(); | 498 | mmu_switch_buff(); |
498 | 499 | ||
499 | last_disk_activity = current_tick; | ||
500 | |||
501 | /* transfer data from receive buffer to the dest | ||
502 | * for (i=0; i<(512/4); i++) | ||
503 | * *dst++ = MMU_DATA; | ||
504 | * | ||
505 | * below is DMA version in software mode. | ||
506 | * SD module provides DMAreq signals and all this | ||
507 | * can be done in hardware in theory but I can't | ||
508 | * figure this out. OF doesn't use DMA at all. | ||
509 | */ | ||
510 | A2A_IDST0 = (unsigned long)dst; | 500 | A2A_IDST0 = (unsigned long)dst; |
511 | A2A_CON0 = (3<<9) | (1<<6) | (1<<3) | (2<<1) | (1<<0); | 501 | A2A_CON0 = (3<<9) | /* burst 16 */ |
502 | (1<<6) | /* fixed src */ | ||
503 | (1<<3) | /* DMA start */ | ||
504 | (2<<1) | /* word transfer size */ | ||
505 | (1<<0); /* software mode */ | ||
512 | 506 | ||
513 | /* wait for DMA engine to finish transfer */ | 507 | /* wait for DMA engine to finish transfer */ |
514 | while (A2A_DMA_STS & 1); | 508 | while (A2A_DMA_STS & 1); |
515 | 509 | ||
516 | dst += 512; | 510 | dst += 512; |
517 | cnt--; | 511 | cnt--; |
518 | } /* while (cnt > 0) */ | ||
519 | 512 | ||
520 | if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response)) | 513 | if (cnt == 0) |
521 | ret = -6; | 514 | { |
515 | if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response)) | ||
516 | ret = -4; | ||
517 | |||
518 | break; | ||
519 | } | ||
520 | else if (cnt == 1) | ||
521 | { | ||
522 | /* last block to tranfer */ | ||
523 | SD_DATAT = DATA_XFER_START | DATA_XFER_READ | | ||
524 | DATA_BUS_1LINE | DATA_XFER_DMA_DIS | | ||
525 | DATA_XFER_SINGLE; | ||
526 | } | ||
527 | else | ||
528 | { | ||
529 | /* more than one block to transfer */ | ||
530 | SD_DATAT = DATA_XFER_START | DATA_XFER_READ | | ||
531 | DATA_BUS_1LINE | DATA_XFER_DMA_DIS | | ||
532 | DATA_XFER_MULTI; | ||
533 | } | ||
534 | |||
535 | last_disk_activity = current_tick; | ||
536 | |||
537 | } /* while (cnt > 0) */ | ||
522 | 538 | ||
523 | /* transfer successfull - leave retry loop */ | 539 | /* transfer successfull - leave retry loop */ |
524 | if (ret == 0) | 540 | if (ret == 0) |
525 | break; | 541 | break; |
526 | } | 542 | |
543 | } /* while (retry_cnt++ < 20) */ | ||
527 | 544 | ||
528 | sd_enable(false); | 545 | sd_enable(false); |
529 | mutex_unlock(&sd_mtx); | 546 | mutex_unlock(&sd_mtx); |
@@ -548,7 +565,7 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count, | |||
548 | unsigned int retry_cnt = 0; | 565 | unsigned int retry_cnt = 0; |
549 | int cnt, ret = 0; | 566 | int cnt, ret = 0; |
550 | unsigned char *src; | 567 | unsigned char *src; |
551 | bool card_selected = false; | 568 | /* bool card_selected = false; */ |
552 | 569 | ||
553 | mutex_lock(&sd_mtx); | 570 | mutex_lock(&sd_mtx); |
554 | sd_enable(true); | 571 | sd_enable(true); |
@@ -574,6 +591,18 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count, | |||
574 | retry = false; /* reset retry flag */ | 591 | retry = false; /* reset retry flag */ |
575 | mmu_buff_reset(); /* reset recive buff state */ | 592 | mmu_buff_reset(); /* reset recive buff state */ |
576 | 593 | ||
594 | /* transfer data from receive buffer to the dest | ||
595 | * for (i=0; i<(512/4); i++) | ||
596 | * MMU_DATA = *src++; | ||
597 | * | ||
598 | * Below is DMA version in software mode. | ||
599 | */ | ||
600 | |||
601 | A2A_ISRC0 = (unsigned long)src; | ||
602 | A2A_CON0 = (3<<9) | (1<<5) | (1<<3) | (2<<1) | (1<<0); | ||
603 | |||
604 | while (A2A_DMA_STS & 1); | ||
605 | |||
577 | if (!send_cmd(SD_WRITE_MULTIPLE_BLOCK, start, RES_R1, &response)) | 606 | if (!send_cmd(SD_WRITE_MULTIPLE_BLOCK, start, RES_R1, &response)) |
578 | { | 607 | { |
579 | ret = -3; | 608 | ret = -3; |
@@ -582,20 +611,6 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count, | |||
582 | 611 | ||
583 | while (cnt > 0) | 612 | while (cnt > 0) |
584 | { | 613 | { |
585 | /* transfer data from receive buffer to the dest | ||
586 | * for (i=0; i<(512/4); i++) | ||
587 | * MMU_DATA = *src++; | ||
588 | * | ||
589 | * Below is DMA version in software mode. | ||
590 | */ | ||
591 | |||
592 | A2A_ISRC0 = (unsigned long)src; | ||
593 | A2A_CON0 = (3<<9) | (1<<5) | (1<<3) | (2<<1) | (1<<0); | ||
594 | |||
595 | while (A2A_DMA_STS & 1); | ||
596 | |||
597 | src += 512; | ||
598 | |||
599 | /* exchange buffers */ | 614 | /* exchange buffers */ |
600 | mmu_switch_buff(); | 615 | mmu_switch_buff(); |
601 | 616 | ||
@@ -614,6 +629,18 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count, | |||
614 | DATA_BUS_1LINE | DATA_XFER_DMA_DIS | | 629 | DATA_BUS_1LINE | DATA_XFER_DMA_DIS | |
615 | DATA_XFER_MULTI; | 630 | DATA_XFER_MULTI; |
616 | 631 | ||
632 | /* transfer data from receive buffer to the dest | ||
633 | * for (i=0; i<(512/4); i++) | ||
634 | * MMU_DATA = *src++; | ||
635 | * | ||
636 | * Below is DMA version in software mode. | ||
637 | */ | ||
638 | src += 512; | ||
639 | |||
640 | A2A_ISRC0 = (unsigned long)src; | ||
641 | A2A_CON0 = (3<<9) | (1<<5) | (1<<3) | (2<<1) | (1<<0); | ||
642 | |||
643 | while (A2A_DMA_STS & 1); | ||
617 | } | 644 | } |
618 | 645 | ||
619 | /* wait for transfer completion */ | 646 | /* wait for transfer completion */ |