diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c | 131 |
1 files changed, 90 insertions, 41 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c index 0717f80b9d..881c83066e 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c | |||
@@ -29,10 +29,12 @@ | |||
29 | #include "logf.h" | 29 | #include "logf.h" |
30 | #include "storage.h" | 30 | #include "storage.h" |
31 | #include "string.h" | 31 | #include "string.h" |
32 | #include "panic.h" | ||
32 | 33 | ||
33 | #define SD_INTERRUPT 0 | 34 | #define SD_INTERRUPT 0 // COMPLETELY BROKEN! |
34 | #define SD_DMA_ENABLE 1 | 35 | #define SD_DMA_ENABLE 1 |
35 | #define SD_DMA_INTERRUPT 0 | 36 | #define SD_DMA_INTERRUPT 1 // HANGS RANDOMLY! |
37 | #define SD_AUTO_CLOCK 1 | ||
36 | 38 | ||
37 | #if NUM_DRIVES > 2 | 39 | #if NUM_DRIVES > 2 |
38 | #error "JZ4760 SD driver supports NUM_DRIVES <= 2 only" | 40 | #error "JZ4760 SD driver supports NUM_DRIVES <= 2 only" |
@@ -267,6 +269,14 @@ static inline int jz_sd_stop_clock(const int drive) | |||
267 | register int timeout = 1000; | 269 | register int timeout = 1000; |
268 | 270 | ||
269 | //DEBUG("stop MMC clock"); | 271 | //DEBUG("stop MMC clock"); |
272 | #if SD_AUTO_CLOCK | ||
273 | REG_MSC_LPM(drive) = 0; /* disable auto clock stop */ | ||
274 | #endif | ||
275 | |||
276 | /* only stop if necessary */ | ||
277 | if (!(REG_MSC_STAT(MSC_CHN(drive)) & MSC_STAT_CLK_EN)) | ||
278 | return SD_NO_ERROR; | ||
279 | |||
270 | REG_MSC_STRPCL(MSC_CHN(drive)) = MSC_STRPCL_CLOCK_CONTROL_STOP; | 280 | REG_MSC_STRPCL(MSC_CHN(drive)) = MSC_STRPCL_CLOCK_CONTROL_STOP; |
271 | 281 | ||
272 | while (timeout && (REG_MSC_STAT(MSC_CHN(drive)) & MSC_STAT_CLK_EN)) | 282 | while (timeout && (REG_MSC_STAT(MSC_CHN(drive)) & MSC_STAT_CLK_EN)) |
@@ -279,6 +289,7 @@ static inline int jz_sd_stop_clock(const int drive) | |||
279 | } | 289 | } |
280 | udelay(1); | 290 | udelay(1); |
281 | } | 291 | } |
292 | |||
282 | //DEBUG("clock off time is %d microsec", timeout); | 293 | //DEBUG("clock off time is %d microsec", timeout); |
283 | return SD_NO_ERROR; | 294 | return SD_NO_ERROR; |
284 | } | 295 | } |
@@ -286,7 +297,11 @@ static inline int jz_sd_stop_clock(const int drive) | |||
286 | /* Start the MMC clock and operation */ | 297 | /* Start the MMC clock and operation */ |
287 | static inline int jz_sd_start_clock(const int drive) | 298 | static inline int jz_sd_start_clock(const int drive) |
288 | { | 299 | { |
289 | REG_MSC_STRPCL(MSC_CHN(drive)) = MSC_STRPCL_CLOCK_CONTROL_START | MSC_STRPCL_START_OP; | 300 | int reg = MSC_STRPCL_START_OP; |
301 | #if !SD_AUTO_CLOCK | ||
302 | reg |= (REG_MSC_STAT(MSC_CHN(drive)) & MSC_STAT_CLK_EN) ? 0 : MSC_STRPCL_CLOCK_CONTROL_START; | ||
303 | #endif | ||
304 | REG_MSC_STRPCL(MSC_CHN(drive)) = reg; | ||
290 | return SD_NO_ERROR; | 305 | return SD_NO_ERROR; |
291 | } | 306 | } |
292 | 307 | ||
@@ -588,91 +603,88 @@ void DMA_CALLBACK(DMA_SD_RX_CHANNEL0)(void) | |||
588 | { | 603 | { |
589 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_AR) | 604 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_AR) |
590 | { | 605 | { |
591 | logf("SD RX DMA address error"); | ||
592 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_AR; | 606 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_AR; |
607 | panicf("SD RX DMA address error"); | ||
593 | } | 608 | } |
594 | 609 | ||
595 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_HLT) | 610 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_HLT) |
596 | { | 611 | { |
597 | logf("SD RX DMA halt"); | ||
598 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_HLT; | 612 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_HLT; |
613 | panicf("SD RX DMA halt"); | ||
599 | } | 614 | } |
600 | 615 | ||
601 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_TT) | 616 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_TT) |
602 | { | 617 | { |
603 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_TT; | 618 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_TT; |
604 | //sd_rx_dma_callback(); | 619 | //sd_rx_dma_callback(); |
620 | semaphore_release(&sd_wakeup[SD_SLOT_1]); | ||
605 | } | 621 | } |
606 | |||
607 | semaphore_release(&sd_wakeup[SD_SLOT_1]); | ||
608 | } | 622 | } |
609 | 623 | ||
610 | void DMA_CALLBACK(DMA_SD_RX_CHANNEL1)(void) | 624 | void DMA_CALLBACK(DMA_SD_RX_CHANNEL1)(void) |
611 | { | 625 | { |
612 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_AR) | 626 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_AR) |
613 | { | 627 | { |
614 | logf("SD RX DMA address error"); | ||
615 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_AR; | 628 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_AR; |
629 | panicf("SD RX DMA address error"); | ||
616 | } | 630 | } |
617 | 631 | ||
618 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_HLT) | 632 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_HLT) |
619 | { | 633 | { |
620 | logf("SD RX DMA halt"); | ||
621 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_HLT; | 634 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_HLT; |
635 | panicf("SD RX DMA halt"); | ||
622 | } | 636 | } |
623 | 637 | ||
624 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_TT) | 638 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_TT) |
625 | { | 639 | { |
626 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_TT; | 640 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_TT; |
627 | //sd_rx_dma_callback(); | 641 | //sd_rx_dma_callback(); |
642 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | ||
628 | } | 643 | } |
629 | |||
630 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | ||
631 | } | 644 | } |
632 | 645 | ||
633 | void DMA_CALLBACK(DMA_SD_TX_CHANNEL0)(void) | 646 | void DMA_CALLBACK(DMA_SD_TX_CHANNEL0)(void) |
634 | { | 647 | { |
635 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_AR) | 648 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_AR) |
636 | { | 649 | { |
637 | logf("SD TX DMA address error: %x, %x, %x", var1, var2, var3); | ||
638 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_AR; | 650 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_AR; |
651 | panicf("SD TX DMA address error"); | ||
639 | } | 652 | } |
640 | 653 | ||
641 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_HLT) | 654 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_HLT) |
642 | { | 655 | { |
643 | logf("SD TX DMA halt"); | ||
644 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_HLT; | 656 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_HLT; |
657 | panicf("SD TX DMA halt"); | ||
645 | } | 658 | } |
646 | 659 | ||
647 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_TT) | 660 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_TT) |
648 | { | 661 | { |
649 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_TT; | 662 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_TT; |
650 | //sd_tx_dma_callback(); | 663 | //sd_tx_dma_callback(); |
664 | semaphore_release(&sd_wakeup[SD_SLOT_1]); | ||
651 | } | 665 | } |
652 | |||
653 | semaphore_release(&sd_wakeup[SD_SLOT_1]); | ||
654 | } | 666 | } |
667 | |||
655 | void DMA_CALLBACK(DMA_SD_TX_CHANNEL1)(void) | 668 | void DMA_CALLBACK(DMA_SD_TX_CHANNEL1)(void) |
656 | { | 669 | { |
657 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_AR) | 670 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_AR) |
658 | { | 671 | { |
659 | logf("SD TX DMA address error: %x, %x, %x", var1, var2, var3); | ||
660 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_AR; | 672 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_AR; |
673 | panicf("SD TX DMA address error"); | ||
661 | } | 674 | } |
662 | 675 | ||
663 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_HLT) | 676 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_HLT) |
664 | { | 677 | { |
665 | logf("SD TX DMA halt"); | ||
666 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_HLT; | 678 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_HLT; |
679 | panicf("SD TX DMA halt"); | ||
667 | } | 680 | } |
668 | 681 | ||
669 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_TT) | 682 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_TT) |
670 | { | 683 | { |
671 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_TT; | 684 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_TT; |
672 | //sd_tx_dma_callback(); | 685 | //sd_tx_dma_callback(); |
686 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | ||
673 | } | 687 | } |
674 | |||
675 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | ||
676 | } | 688 | } |
677 | #endif /* SD_DMA_INTERRUPT */ | 689 | #endif /* SD_DMA_INTERRUPT */ |
678 | #endif /* SD_DMA_ENABLE */ | 690 | #endif /* SD_DMA_ENABLE */ |
@@ -715,8 +727,6 @@ static void jz_sd_set_clock(const int drive, unsigned int rate) | |||
715 | { | 727 | { |
716 | int clkrt; | 728 | int clkrt; |
717 | 729 | ||
718 | jz_sd_stop_clock(drive); | ||
719 | |||
720 | /* select clock source from CPM */ | 730 | /* select clock source from CPM */ |
721 | cpm_select_msc_clk(); | 731 | cpm_select_msc_clk(); |
722 | 732 | ||
@@ -747,28 +757,27 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
747 | /* On reset, 1-bit bus width */ | 757 | /* On reset, 1-bit bus width */ |
748 | use_4bit[drive] = 0; | 758 | use_4bit[drive] = 0; |
749 | 759 | ||
760 | /* On reset, stop SD clock */ | ||
761 | jz_sd_stop_clock(drive); | ||
762 | |||
750 | /* Reset MMC/SD controller */ | 763 | /* Reset MMC/SD controller */ |
751 | __msc_reset(MSC_CHN(drive)); | 764 | __msc_reset(MSC_CHN(drive)); |
752 | 765 | ||
753 | /* On reset, drop SD clock down */ | 766 | /* Drop SD clock down to lowest speed */ |
754 | jz_sd_set_clock(drive, MMC_CLOCK_SLOW); | 767 | jz_sd_set_clock(drive, MMC_CLOCK_SLOW); |
755 | 768 | ||
756 | /* On reset, stop SD clock */ | 769 | #if SD_AUTO_CLOCK |
757 | jz_sd_stop_clock(drive); | 770 | /* Re-enable clocks */ |
771 | REG_MSC_STRPCL(MSC_CHN(drive)) = MSC_STRPCL_CLOCK_CONTROL_START; | ||
772 | REG_MSC_LPM(drive) = MSC_SET_LPM; | ||
773 | #endif | ||
758 | } | 774 | } |
759 | 775 | ||
760 | /* stop clock */ | ||
761 | jz_sd_stop_clock(drive); | ||
762 | |||
763 | /* mask all interrupts and clear status */ | 776 | /* mask all interrupts and clear status */ |
764 | SD_IRQ_MASK(MSC_CHN(drive)); | 777 | SD_IRQ_MASK(MSC_CHN(drive)); |
765 | 778 | ||
766 | /* open interrupt */ | 779 | /* open interrupt */ |
767 | #if SD_INTERRUPT | ||
768 | REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE); | ||
769 | #else | ||
770 | REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE); | 780 | REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE); |
771 | #endif | ||
772 | 781 | ||
773 | /* Set command type and events */ | 782 | /* Set command type and events */ |
774 | switch (request->cmd) | 783 | switch (request->cmd) |
@@ -926,8 +935,8 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
926 | return SD_ERROR_TIMEOUT; | 935 | return SD_ERROR_TIMEOUT; |
927 | yield(); | 936 | yield(); |
928 | } | 937 | } |
929 | #endif | ||
930 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_END_CMD_RES; /* clear flag */ | 938 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_END_CMD_RES; /* clear flag */ |
939 | #endif | ||
931 | 940 | ||
932 | /* Check for status */ | 941 | /* Check for status */ |
933 | retval = jz_sd_check_status(drive, request); | 942 | retval = jz_sd_check_status(drive, request); |
@@ -964,8 +973,8 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
964 | /* Wait for Data Done */ | 973 | /* Wait for Data Done */ |
965 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_DATA_TRAN_DONE)) | 974 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_DATA_TRAN_DONE)) |
966 | yield(); | 975 | yield(); |
967 | #endif | ||
968 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_DATA_TRAN_DONE; /* clear status */ | 976 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_DATA_TRAN_DONE; /* clear status */ |
977 | #endif | ||
969 | } | 978 | } |
970 | 979 | ||
971 | /* Wait for Prog Done event */ | 980 | /* Wait for Prog Done event */ |
@@ -976,11 +985,14 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
976 | #else | 985 | #else |
977 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_PRG_DONE)) | 986 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_PRG_DONE)) |
978 | yield(); | 987 | yield(); |
979 | #endif | ||
980 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_PRG_DONE; /* clear status */ | 988 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_PRG_DONE; /* clear status */ |
989 | #endif | ||
981 | } | 990 | } |
982 | 991 | ||
983 | /* Command completed */ | 992 | /* Command completed */ |
993 | #if !SD_AUTO_CLOCK | ||
994 | jz_sd_stop_clock(drive); /* stop SD clock */ | ||
995 | #endif | ||
984 | 996 | ||
985 | return SD_NO_ERROR; /* return successfully */ | 997 | return SD_NO_ERROR; /* return successfully */ |
986 | } | 998 | } |
@@ -996,17 +1008,44 @@ static int jz_sd_chkcard(const int drive) | |||
996 | return (__gpio_get_pin((drive == SD_SLOT_1) ? PIN_SD1_CD : PIN_SD2_CD) == 0 ? 1 : 0); | 1008 | return (__gpio_get_pin((drive == SD_SLOT_1) ? PIN_SD1_CD : PIN_SD2_CD) == 0 ? 1 : 0); |
997 | } | 1009 | } |
998 | 1010 | ||
999 | /* MSC interrupt handler */ | 1011 | /* MSC interrupt handlers */ |
1000 | void MSC(void) | ||
1001 | { | ||
1002 | #if SD_INTERRUPT | 1012 | #if SD_INTERRUPT |
1003 | if (REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) & MSC_IREG_DATA_TRAN_DONE) | 1013 | void MSC2(void) /* SD_SLOT_1 */ |
1014 | { | ||
1015 | logf("MSC2 interrupt"); | ||
1016 | |||
1017 | if (REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) & MSC_IREG_END_CMD_RES) { | ||
1018 | REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) = MSC_IREG_END_CMD_RES; /* clear flag */ | ||
1004 | semaphore_release(&sd_wakeup[SD_SLOT_1]); | 1019 | semaphore_release(&sd_wakeup[SD_SLOT_1]); |
1005 | else if (REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) & MSC_IREG_DATA_TRAN_DONE) | 1020 | } |
1021 | if (REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) & MSC_IREG_PRG_DONE) { | ||
1022 | REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) = MSC_IREG_PRG_DONE; /* clear flag */ | ||
1023 | semaphore_release(&sd_wakeup[SD_SLOT_1]); | ||
1024 | } | ||
1025 | if (REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) & MSC_IREG_DATA_TRAN_DONE) { | ||
1026 | REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) = MSC_IREG_DATA_TRAN_DONE; /* clear flag */ | ||
1027 | semaphore_release(&sd_wakeup[SD_SLOT_1]); | ||
1028 | } | ||
1029 | } | ||
1030 | |||
1031 | /* MSC interrupt handlers */ | ||
1032 | void MSC1(void) /* SD_SLOT_2 */ | ||
1033 | { | ||
1034 | logf("MSC1 interrupt"); | ||
1035 | if (REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) & MSC_IREG_END_CMD_RES) { | ||
1036 | REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) = MSC_IREG_END_CMD_RES; /* clear flag */ | ||
1006 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | 1037 | semaphore_release(&sd_wakeup[SD_SLOT_2]); |
1007 | #endif | 1038 | } |
1008 | logf("MSC interrupt"); | 1039 | if (REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) & MSC_IREG_PRG_DONE) { |
1040 | REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) = MSC_IREG_PRG_DONE; /* clear flag */ | ||
1041 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | ||
1042 | } | ||
1043 | if (REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) & MSC_IREG_DATA_TRAN_DONE) { | ||
1044 | REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) = MSC_IREG_DATA_TRAN_DONE; /* clear flag */ | ||
1045 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | ||
1046 | } | ||
1009 | } | 1047 | } |
1048 | #endif | ||
1010 | 1049 | ||
1011 | #ifdef HAVE_HOTSWAP | 1050 | #ifdef HAVE_HOTSWAP |
1012 | static void sd_gpio_setup_irq(const int drive, bool inserted) | 1051 | static void sd_gpio_setup_irq(const int drive, bool inserted) |
@@ -1038,7 +1077,12 @@ static void jz_sd_hardware_init(const int drive) | |||
1038 | #endif | 1077 | #endif |
1039 | __msc_reset(MSC_CHN(drive)); /* reset mmc/sd controller */ | 1078 | __msc_reset(MSC_CHN(drive)); /* reset mmc/sd controller */ |
1040 | SD_IRQ_MASK(MSC_CHN(drive)); /* mask all IRQs */ | 1079 | SD_IRQ_MASK(MSC_CHN(drive)); /* mask all IRQs */ |
1080 | #if SD_AUTO_CLOCK | ||
1081 | REG_MSC_STRPCL(MSC_CHN(drive)) = MSC_STRPCL_CLOCK_CONTROL_START; /* Enable clocks */ | ||
1082 | REG_MSC_LPM(drive) = MSC_SET_LPM; /* enable auto clock stop */ | ||
1083 | #else | ||
1041 | jz_sd_stop_clock(drive); /* stop SD clock */ | 1084 | jz_sd_stop_clock(drive); /* stop SD clock */ |
1085 | #endif | ||
1042 | } | 1086 | } |
1043 | 1087 | ||
1044 | static void sd_send_cmd(const int drive, struct sd_request *request, int cmd, unsigned int arg, | 1088 | static void sd_send_cmd(const int drive, struct sd_request *request, int cmd, unsigned int arg, |
@@ -1315,6 +1359,11 @@ int sd_init(void) | |||
1315 | mutex_init(&sd_mtx[SD_SLOT_1]); | 1359 | mutex_init(&sd_mtx[SD_SLOT_1]); |
1316 | mutex_init(&sd_mtx[SD_SLOT_2]); | 1360 | mutex_init(&sd_mtx[SD_SLOT_2]); |
1317 | 1361 | ||
1362 | #if SD_INTERRUPT | ||
1363 | system_enable_irq(IRQ_MSC2); | ||
1364 | system_enable_irq(IRQ_MSC1); | ||
1365 | #endif | ||
1366 | |||
1318 | #if SD_DMA_ENABLE && SD_DMA_INTERRUPT | 1367 | #if SD_DMA_ENABLE && SD_DMA_INTERRUPT |
1319 | system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL(SD_SLOT_1))); | 1368 | system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL(SD_SLOT_1))); |
1320 | system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL(SD_SLOT_2))); | 1369 | system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL(SD_SLOT_2))); |