diff options
author | Michael Sparmann <theseven@rockbox.org> | 2011-02-27 22:47:55 +0000 |
---|---|---|
committer | Michael Sparmann <theseven@rockbox.org> | 2011-02-27 22:47:55 +0000 |
commit | 30fb680a4dc7b8f1fed9002a47dc2154c7f72d0a (patch) | |
tree | 3f685583a92719314cf722fb8a8737947bb968c1 /firmware | |
parent | 59c5e791a13765e75dacc2b97e93450c374b3b14 (diff) | |
download | rockbox-30fb680a4dc7b8f1fed9002a47dc2154c7f72d0a.tar.gz rockbox-30fb680a4dc7b8f1fed9002a47dc2154c7f72d0a.zip |
iPod Classic CE-ATA Support (Part 4 of 4: S5L8702 ATA driver)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29448 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/SOURCES | 4 | ||||
-rw-r--r-- | firmware/export/config/ipod6g.h | 11 | ||||
-rw-r--r-- | firmware/export/s5l8702.h | 210 | ||||
-rw-r--r-- | firmware/target/arm/s5l8700/app.lds | 2 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/app.lds | 2 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c | 197 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/ata-target.h | 47 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/mmcdefs-target.h | 345 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c | 1142 | ||||
-rw-r--r-- | firmware/target/arm/s5l8702/system-s5l8702.c | 6 |
10 files changed, 1702 insertions, 264 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index b2b353bda2..e0186af966 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES | |||
@@ -209,7 +209,7 @@ target/arm/ata-nand-telechips.c | |||
209 | #if (CONFIG_STORAGE & STORAGE_NAND) && (CONFIG_NAND == NAND_SAMSUNG) | 209 | #if (CONFIG_STORAGE & STORAGE_NAND) && (CONFIG_NAND == NAND_SAMSUNG) |
210 | target/arm/s5l8700/ata-nand-s5l8700.c | 210 | target/arm/s5l8700/ata-nand-s5l8700.c |
211 | #endif | 211 | #endif |
212 | #if (CONFIG_STORAGE & STORAGE_ATA) | 212 | #if (CONFIG_STORAGE & STORAGE_ATA) && !defined(IPOD_6G) |
213 | drivers/ata.c | 213 | drivers/ata.c |
214 | #endif | 214 | #endif |
215 | #if (CONFIG_STORAGE & STORAGE_SD) | 215 | #if (CONFIG_STORAGE & STORAGE_SD) |
@@ -1551,6 +1551,7 @@ target/arm/s5l8700/ipodnano2g/adc-nano2g.c | |||
1551 | #ifdef IPOD_6G | 1551 | #ifdef IPOD_6G |
1552 | #ifndef SIMULATOR | 1552 | #ifndef SIMULATOR |
1553 | target/arm/ipod/button-clickwheel.c | 1553 | target/arm/ipod/button-clickwheel.c |
1554 | target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c | ||
1554 | target/arm/s5l8702/ipod6g/cscodec-ipod6g.c | 1555 | target/arm/s5l8702/ipod6g/cscodec-ipod6g.c |
1555 | target/arm/s5l8702/ipod6g/backlight-ipod6g.c | 1556 | target/arm/s5l8702/ipod6g/backlight-ipod6g.c |
1556 | target/arm/s5l8702/ipod6g/powermgmt-ipod6g.c | 1557 | target/arm/s5l8702/ipod6g/powermgmt-ipod6g.c |
@@ -1559,7 +1560,6 @@ target/arm/s5l8702/kernel-s5l8702.c | |||
1559 | target/arm/s5l8702/system-s5l8702.c | 1560 | target/arm/s5l8702/system-s5l8702.c |
1560 | target/arm/s5l8702/ipod6g/lcd-ipod6g.c | 1561 | target/arm/s5l8702/ipod6g/lcd-ipod6g.c |
1561 | target/arm/s5l8702/ipod6g/lcd-asm-ipod6g.S | 1562 | target/arm/s5l8702/ipod6g/lcd-asm-ipod6g.S |
1562 | target/arm/s5l8702/ipod6g/ata-ipod6g.c | ||
1563 | #if 0 //TODO | 1563 | #if 0 //TODO |
1564 | target/arm/s5l8702/postmortemstub.S | 1564 | target/arm/s5l8702/postmortemstub.S |
1565 | #endif | 1565 | #endif |
diff --git a/firmware/export/config/ipod6g.h b/firmware/export/config/ipod6g.h index 6ab89e5869..e783612364 100644 --- a/firmware/export/config/ipod6g.h +++ b/firmware/export/config/ipod6g.h | |||
@@ -185,13 +185,20 @@ | |||
185 | /* Define this if you can read an absolute wheel position */ | 185 | /* Define this if you can read an absolute wheel position */ |
186 | #define HAVE_WHEEL_POSITION | 186 | #define HAVE_WHEEL_POSITION |
187 | 187 | ||
188 | //#define HAVE_ATA_BBT | ||
189 | //#define ATA_BBT_PAGES 3072 | ||
190 | |||
191 | #define SECTOR_SIZE 4096 | ||
192 | |||
193 | #define STORAGE_NEEDS_ALIGN | ||
194 | |||
188 | /* define this if the device has larger sectors when accessed via USB */ | 195 | /* define this if the device has larger sectors when accessed via USB */ |
189 | /* (only relevant in disk.c, fat.c now always supports large virtual sectors) */ | 196 | /* (only relevant in disk.c, fat.c now always supports large virtual sectors) */ |
190 | #define MAX_LOG_SECTOR_SIZE 4096 | 197 | //#define MAX_LOG_SECTOR_SIZE 4096 |
191 | 198 | ||
192 | /* define this if the hard drive uses large physical sectors (ATA-7 feature) */ | 199 | /* define this if the hard drive uses large physical sectors (ATA-7 feature) */ |
193 | /* and doesn't handle them in the drive firmware */ | 200 | /* and doesn't handle them in the drive firmware */ |
194 | #define MAX_PHYS_SECTOR_SIZE 4096 | 201 | //#define MAX_PHYS_SECTOR_SIZE 4096 |
195 | 202 | ||
196 | /* Define this if you have adjustable CPU frequency */ | 203 | /* Define this if you have adjustable CPU frequency */ |
197 | #define HAVE_ADJUSTABLE_CPU_FREQ | 204 | #define HAVE_ADJUSTABLE_CPU_FREQ |
diff --git a/firmware/export/s5l8702.h b/firmware/export/s5l8702.h index 076e661fa4..ebd3eda2bb 100644 --- a/firmware/export/s5l8702.h +++ b/firmware/export/s5l8702.h | |||
@@ -568,9 +568,9 @@ struct dma_lli | |||
568 | 568 | ||
569 | 569 | ||
570 | /////ATA///// | 570 | /////ATA///// |
571 | #define ATA_CCONTROL (*((uint32_t volatile*)(0x38700000))) | 571 | #define ATA_CONTROL (*((uint32_t volatile*)(0x38700000))) |
572 | #define ATA_CSTATUS (*((uint32_t volatile*)(0x38700004))) | 572 | #define ATA_STATUS (*((uint32_t volatile*)(0x38700004))) |
573 | #define ATA_CCOMMAND (*((uint32_t volatile*)(0x38700008))) | 573 | #define ATA_COMMAND (*((uint32_t volatile*)(0x38700008))) |
574 | #define ATA_SWRST (*((uint32_t volatile*)(0x3870000c))) | 574 | #define ATA_SWRST (*((uint32_t volatile*)(0x3870000c))) |
575 | #define ATA_IRQ (*((uint32_t volatile*)(0x38700010))) | 575 | #define ATA_IRQ (*((uint32_t volatile*)(0x38700010))) |
576 | #define ATA_IRQ_MASK (*((uint32_t volatile*)(0x38700014))) | 576 | #define ATA_IRQ_MASK (*((uint32_t volatile*)(0x38700014))) |
@@ -586,15 +586,15 @@ struct dma_lli | |||
586 | #define ATA_SBUF_SIZE (*((uint32_t volatile*)(0x38700048))) | 586 | #define ATA_SBUF_SIZE (*((uint32_t volatile*)(0x38700048))) |
587 | #define ATA_CADR_TBUF (*((void* volatile*)(0x3870004c))) | 587 | #define ATA_CADR_TBUF (*((void* volatile*)(0x3870004c))) |
588 | #define ATA_CADR_SBUF (*((void* volatile*)(0x38700050))) | 588 | #define ATA_CADR_SBUF (*((void* volatile*)(0x38700050))) |
589 | #define ATA_DATA ((uint32_t volatile*)(0x38700054)) | 589 | #define ATA_PIO_DTR (*((uint32_t volatile*)(0x38700054))) |
590 | #define ATA_ERROR ((uint32_t volatile*)(0x38700058)) | 590 | #define ATA_PIO_FED (*((uint32_t volatile*)(0x38700058))) |
591 | #define ATA_NSECTOR ((uint32_t volatile*)(0x3870005c)) | 591 | #define ATA_PIO_SCR (*((uint32_t volatile*)(0x3870005c))) |
592 | #define ATA_SECTOR ((uint32_t volatile*)(0x38700060)) | 592 | #define ATA_PIO_LLR (*((uint32_t volatile*)(0x38700060))) |
593 | #define ATA_LCYL ((uint32_t volatile*)(0x38700064)) | 593 | #define ATA_PIO_LMR (*((uint32_t volatile*)(0x38700064))) |
594 | #define ATA_HCYL ((uint32_t volatile*)(0x38700068)) | 594 | #define ATA_PIO_LHR (*((uint32_t volatile*)(0x38700068))) |
595 | #define ATA_SELECT ((uint32_t volatile*)(0x3870006c)) | 595 | #define ATA_PIO_DVR (*((uint32_t volatile*)(0x3870006c))) |
596 | #define ATA_COMMAND ((uint32_t volatile*)(0x38700070)) | 596 | #define ATA_PIO_CSD (*((uint32_t volatile*)(0x38700070))) |
597 | #define ATA_CONTROL ((uint32_t volatile*)(0x38700074)) | 597 | #define ATA_PIO_DAD (*((uint32_t volatile*)(0x38700074))) |
598 | #define ATA_PIO_READY (*((uint32_t volatile*)(0x38700078))) | 598 | #define ATA_PIO_READY (*((uint32_t volatile*)(0x38700078))) |
599 | #define ATA_PIO_RDATA (*((uint32_t volatile*)(0x3870007c))) | 599 | #define ATA_PIO_RDATA (*((uint32_t volatile*)(0x3870007c))) |
600 | #define ATA_BUS_FIFO_STATUS (*((uint32_t volatile*)(0x38700080))) | 600 | #define ATA_BUS_FIFO_STATUS (*((uint32_t volatile*)(0x38700080))) |
@@ -602,6 +602,190 @@ struct dma_lli | |||
602 | #define ATA_DMA_ADDR (*((void* volatile*)(0x38700088))) | 602 | #define ATA_DMA_ADDR (*((void* volatile*)(0x38700088))) |
603 | 603 | ||
604 | 604 | ||
605 | /////SDCI///// | ||
606 | #define SDCI_CTRL (*((uint32_t volatile*)(0x38b00000))) | ||
607 | #define SDCI_DCTRL (*((uint32_t volatile*)(0x38b00004))) | ||
608 | #define SDCI_CMD (*((uint32_t volatile*)(0x38b00008))) | ||
609 | #define SDCI_ARGU (*((uint32_t volatile*)(0x38b0000c))) | ||
610 | #define SDCI_STATE (*((uint32_t volatile*)(0x38b00010))) | ||
611 | #define SDCI_STAC (*((uint32_t volatile*)(0x38b00014))) | ||
612 | #define SDCI_DSTA (*((uint32_t volatile*)(0x38b00018))) | ||
613 | #define SDCI_FSTA (*((uint32_t volatile*)(0x38b0001c))) | ||
614 | #define SDCI_RESP0 (*((uint32_t volatile*)(0x38b00020))) | ||
615 | #define SDCI_RESP1 (*((uint32_t volatile*)(0x38b00024))) | ||
616 | #define SDCI_RESP2 (*((uint32_t volatile*)(0x38b00028))) | ||
617 | #define SDCI_RESP3 (*((uint32_t volatile*)(0x38b0002c))) | ||
618 | #define SDCI_CDIV (*((uint32_t volatile*)(0x38b00030))) | ||
619 | #define SDCI_SDIO_CSR (*((uint32_t volatile*)(0x38b00034))) | ||
620 | #define SDCI_IRQ (*((uint32_t volatile*)(0x38b00038))) | ||
621 | #define SDCI_IRQ_MASK (*((uint32_t volatile*)(0x38b0003c))) | ||
622 | #define SDCI_DATA (*((uint32_t volatile*)(0x38b00040))) | ||
623 | #define SDCI_DMAADDR (*((void* volatile*)(0x38b00044))) | ||
624 | #define SDCI_DMASIZE (*((uint32_t volatile*)(0x38b00048))) | ||
625 | #define SDCI_DMACOUNT (*((uint32_t volatile*)(0x38b0004c))) | ||
626 | #define SDCI_RESET (*((uint32_t volatile*)(0x38b0006c))) | ||
627 | |||
628 | #define SDCI_CTRL_SDCIEN BIT(0) | ||
629 | #define SDCI_CTRL_CARD_TYPE_MASK BIT(1) | ||
630 | #define SDCI_CTRL_CARD_TYPE_SD 0 | ||
631 | #define SDCI_CTRL_CARD_TYPE_MMC BIT(1) | ||
632 | #define SDCI_CTRL_BUS_WIDTH_MASK BITRANGE(2, 3) | ||
633 | #define SDCI_CTRL_BUS_WIDTH_1BIT 0 | ||
634 | #define SDCI_CTRL_BUS_WIDTH_4BIT BIT(2) | ||
635 | #define SDCI_CTRL_BUS_WIDTH_8BIT BIT(3) | ||
636 | #define SDCI_CTRL_DMA_EN BIT(4) | ||
637 | #define SDCI_CTRL_L_ENDIAN BIT(5) | ||
638 | #define SDCI_CTRL_DMA_REQ_CON_MASK BIT(6) | ||
639 | #define SDCI_CTRL_DMA_REQ_CON_NEMPTY 0 | ||
640 | #define SDCI_CTRL_DMA_REQ_CON_FULL BIT(6) | ||
641 | #define SDCI_CTRL_CLK_SEL_MASK BIT(7) | ||
642 | #define SDCI_CTRL_CLK_SEL_PCLK 0 | ||
643 | #define SDCI_CTRL_CLK_SEL_SDCLK BIT(7) | ||
644 | #define SDCI_CTRL_BIT_8 BIT(8) | ||
645 | #define SDCI_CTRL_BIT_14 BIT(14) | ||
646 | |||
647 | #define SDCI_DCTRL_TXFIFORST BIT(0) | ||
648 | #define SDCI_DCTRL_RXFIFORST BIT(1) | ||
649 | #define SDCI_DCTRL_TRCONT_MASK BITRANGE(4, 5) | ||
650 | #define SDCI_DCTRL_TRCONT_TX BIT(4) | ||
651 | #define SDCI_DCTRL_BUS_TEST_MASK BITRANGE(6, 7) | ||
652 | #define SDCI_DCTRL_BUS_TEST_TX BIT(6) | ||
653 | #define SDCI_DCTRL_BUS_TEST_RX BIT(7) | ||
654 | |||
655 | #define SDCI_CDIV_CLKDIV_MASK BITRANGE(0, 7) | ||
656 | #define SDCI_CDIV_CLKDIV(x) ((x) >> 1) | ||
657 | #define SDCI_CDIV_CLKDIV_2 BIT(0) | ||
658 | #define SDCI_CDIV_CLKDIV_4 BIT(1) | ||
659 | #define SDCI_CDIV_CLKDIV_8 BIT(2) | ||
660 | #define SDCI_CDIV_CLKDIV_16 BIT(3) | ||
661 | #define SDCI_CDIV_CLKDIV_32 BIT(4) | ||
662 | #define SDCI_CDIV_CLKDIV_64 BIT(5) | ||
663 | #define SDCI_CDIV_CLKDIV_128 BIT(6) | ||
664 | #define SDCI_CDIV_CLKDIV_256 BIT(7) | ||
665 | |||
666 | #define SDCI_CMD_CMD_NUM_MASK BITRANGE(0, 5) | ||
667 | #define SDCI_CMD_CMD_NUM_SHIFT 0 | ||
668 | #define SDCI_CMD_CMD_NUM(x) (x) | ||
669 | #define SDCI_CMD_CMD_TYPE_MASK BITRANGE(6, 7) | ||
670 | #define SDCI_CMD_CMD_TYPE_BC 0 | ||
671 | #define SDCI_CMD_CMD_TYPE_BCR BIT(6) | ||
672 | #define SDCI_CMD_CMD_TYPE_AC BIT(7) | ||
673 | #define SDCI_CMD_CMD_TYPE_ADTC (BIT(6) | BIT(7)) | ||
674 | #define SDCI_CMD_CMD_RD_WR BIT(8) | ||
675 | #define SDCI_CMD_RES_TYPE_MASK BITRANGE(16, 18) | ||
676 | #define SDCI_CMD_RES_TYPE_NONE 0 | ||
677 | #define SDCI_CMD_RES_TYPE_R1 BIT(16) | ||
678 | #define SDCI_CMD_RES_TYPE_R2 BIT(17) | ||
679 | #define SDCI_CMD_RES_TYPE_R3 (BIT(16) | BIT(17)) | ||
680 | #define SDCI_CMD_RES_TYPE_R4 BIT(18) | ||
681 | #define SDCI_CMD_RES_TYPE_R5 (BIT(16) | BIT(18)) | ||
682 | #define SDCI_CMD_RES_TYPE_R6 (BIT(17) | BIT(18)) | ||
683 | #define SDCI_CMD_RES_BUSY BIT(19) | ||
684 | #define SDCI_CMD_RES_SIZE_MASK BIT(20) | ||
685 | #define SDCI_CMD_RES_SIZE_48 0 | ||
686 | #define SDCI_CMD_RES_SIZE_136 BIT(20) | ||
687 | #define SDCI_CMD_NCR_NID_MASK BIT(21) | ||
688 | #define SDCI_CMD_NCR_NID_NCR 0 | ||
689 | #define SDCI_CMD_NCR_NID_NID BIT(21) | ||
690 | #define SDCI_CMD_CMDSTR BIT(31) | ||
691 | |||
692 | #define SDCI_STATE_DAT_STATE_MASK BITRANGE(0, 3) | ||
693 | #define SDCI_STATE_DAT_STATE_IDLE 0 | ||
694 | #define SDCI_STATE_DAT_STATE_DAT_RCV BIT(0) | ||
695 | #define SDCI_STATE_DAT_STATE_CRC_RCV BIT(1) | ||
696 | #define SDCI_STATE_DAT_STATE_DAT_END (BIT(0) | BIT(1)) | ||
697 | #define SDCI_STATE_DAT_STATE_DAT_SET BIT(2) | ||
698 | #define SDCI_STATE_DAT_STATE_DAT_OUT (BIT(0) | BIT(2)) | ||
699 | #define SDCI_STATE_DAT_STATE_CRC_TIME (BIT(1) | BIT(2)) | ||
700 | #define SDCI_STATE_DAT_STATE_CRC_OUT (BIT(0) | BIT(1) | BIT(2)) | ||
701 | #define SDCI_STATE_DAT_STATE_ENDB_OUT BIT(3) | ||
702 | #define SDCI_STATE_DAT_STATE_ENDB_STOD (BIT(0) | BIT(3)) | ||
703 | #define SDCI_STATE_DAT_STATE_DAT_CRCR (BIT(1) | BIT(3)) | ||
704 | #define SDCI_STATE_DAT_STATE_CARD_PRG (BIT(0) | BIT(1) | BIT(3)) | ||
705 | #define SDCI_STATE_DAT_STATE_DAT_BUSY (BIT(2) | BIT(3)) | ||
706 | #define SDCI_STATE_CMD_STATE_MASK (BIT(4) | BIT(5) | BIT(6)) | ||
707 | #define SDCI_STATE_CMD_STATE_CMD_IDLE 0 | ||
708 | #define SDCI_STATE_CMD_STATE_CMD_CMDO BIT(4) | ||
709 | #define SDCI_STATE_CMD_STATE_CMD_CRCO BIT(5) | ||
710 | #define SDCI_STATE_CMD_STATE_CMD_TOUT (BIT(4) | BIT(5)) | ||
711 | #define SDCI_STATE_CMD_STATE_CMD_RESR BIT(6) | ||
712 | #define SDCI_STATE_CMD_STATE_CMD_INTV (BIT(4) | BIT(6)) | ||
713 | |||
714 | #define SDCI_STAC_CLR_CMDEND BIT(2) | ||
715 | #define SDCI_STAC_CLR_BIT_3 BIT(3) | ||
716 | #define SDCI_STAC_CLR_RESEND BIT(4) | ||
717 | #define SDCI_STAC_CLR_DATEND BIT(6) | ||
718 | #define SDCI_STAC_CLR_DAT_CRCEND BIT(7) | ||
719 | #define SDCI_STAC_CLR_CRC_STAEND BIT(8) | ||
720 | #define SDCI_STAC_CLR_RESTOUTE BIT(15) | ||
721 | #define SDCI_STAC_CLR_RESENDE BIT(16) | ||
722 | #define SDCI_STAC_CLR_RESINDE BIT(17) | ||
723 | #define SDCI_STAC_CLR_RESCRCE BIT(18) | ||
724 | #define SDCI_STAC_CLR_WR_DATCRCE BIT(22) | ||
725 | #define SDCI_STAC_CLR_RD_DATCRCE BIT(23) | ||
726 | #define SDCI_STAC_CLR_RD_DATENDE0 BIT(24) | ||
727 | #define SDCI_STAC_CLR_RD_DATENDE1 BIT(25) | ||
728 | #define SDCI_STAC_CLR_RD_DATENDE2 BIT(26) | ||
729 | #define SDCI_STAC_CLR_RD_DATENDE3 BIT(27) | ||
730 | #define SDCI_STAC_CLR_RD_DATENDE4 BIT(28) | ||
731 | #define SDCI_STAC_CLR_RD_DATENDE5 BIT(29) | ||
732 | #define SDCI_STAC_CLR_RD_DATENDE6 BIT(30) | ||
733 | #define SDCI_STAC_CLR_RD_DATENDE7 BIT(31) | ||
734 | |||
735 | #define SDCI_DSTA_CMDRDY BIT(0) | ||
736 | #define SDCI_DSTA_CMDPRO BIT(1) | ||
737 | #define SDCI_DSTA_CMDEND BIT(2) | ||
738 | #define SDCI_DSTA_RESPRO BIT(3) | ||
739 | #define SDCI_DSTA_RESEND BIT(4) | ||
740 | #define SDCI_DSTA_DATPRO BIT(5) | ||
741 | #define SDCI_DSTA_DATEND BIT(6) | ||
742 | #define SDCI_DSTA_DAT_CRCEND BIT(7) | ||
743 | #define SDCI_DSTA_CRC_STAEND BIT(8) | ||
744 | #define SDCI_DSTA_DAT_BUSY BIT(9) | ||
745 | #define SDCI_DSTA_SDCLK_HOLD BIT(12) | ||
746 | #define SDCI_DSTA_DAT0_STATUS BIT(13) | ||
747 | #define SDCI_DSTA_WP_DECT_INPUT BIT(14) | ||
748 | #define SDCI_DSTA_RESTOUTE BIT(15) | ||
749 | #define SDCI_DSTA_RESENDE BIT(16) | ||
750 | #define SDCI_DSTA_RESINDE BIT(17) | ||
751 | #define SDCI_DSTA_RESCRCE BIT(18) | ||
752 | #define SDCI_DSTA_WR_CRC_STATUS_MASK BITRANGE(19, 21) | ||
753 | #define SDCI_DSTA_WR_CRC_STATUS_OK BIT(20) | ||
754 | #define SDCI_DSTA_WR_CRC_STATUS_TXERR (BIT(19) | BIT(21)) | ||
755 | #define SDCI_DSTA_WR_CRC_STATUS_CARDERR (BIT(19) | BIT(20) | BIT(21)) | ||
756 | #define SDCI_DSTA_WR_DATCRCE BIT(22) | ||
757 | #define SDCI_DSTA_RD_DATCRCE BIT(23) | ||
758 | #define SDCI_DSTA_RD_DATENDE0 BIT(24) | ||
759 | #define SDCI_DSTA_RD_DATENDE1 BIT(25) | ||
760 | #define SDCI_DSTA_RD_DATENDE2 BIT(26) | ||
761 | #define SDCI_DSTA_RD_DATENDE3 BIT(27) | ||
762 | #define SDCI_DSTA_RD_DATENDE4 BIT(28) | ||
763 | #define SDCI_DSTA_RD_DATENDE5 BIT(29) | ||
764 | #define SDCI_DSTA_RD_DATENDE6 BIT(30) | ||
765 | #define SDCI_DSTA_RD_DATENDE7 BIT(31) | ||
766 | |||
767 | #define SDCI_FSTA_RX_FIFO_EMPTY BIT(0) | ||
768 | #define SDCI_FSTA_RX_FIFO_FULL BIT(1) | ||
769 | #define SDCI_FSTA_TX_FIFO_EMPTY BIT(2) | ||
770 | #define SDCI_FSTA_TX_FIFO_FULL BIT(3) | ||
771 | |||
772 | #define SDCI_SDIO_CSR_SDIO_RW_EN BIT(0) | ||
773 | #define SDCI_SDIO_CSR_SDIO_INT_EN BIT(1) | ||
774 | #define SDCI_SDIO_CSR_SDIO_RW_REQ BIT(2) | ||
775 | #define SDCI_SDIO_CSR_SDIO_RW_STOP BIT(3) | ||
776 | #define SDCI_SDIO_CSR_SDIO_INT_PERIOD_MASK BIT(4) | ||
777 | #define SDCI_SDIO_CSR_SDIO_INT_PERIOD_MORE 0 | ||
778 | #define SDCI_SDIO_CSR_SDIO_INT_PERIOD_XACT BIT(4) | ||
779 | |||
780 | #define SDCI_IRQ_DAT_DONE_INT BIT(0) | ||
781 | #define SDCI_IRQ_IOCARD_IRQ_INT BIT(1) | ||
782 | #define SDCI_IRQ_READ_WAIT_INT BIT(2) | ||
783 | |||
784 | #define SDCI_IRQ_MASK_MASK_DAT_DONE_INT BIT(0) | ||
785 | #define SDCI_IRQ_MASK_MASK_IOCARD_IRQ_INT BIT(1) | ||
786 | #define SDCI_IRQ_MASK_MASK_READ_WAIT_INT BIT(2) | ||
787 | |||
788 | |||
605 | /////CLICKWHEEL///// | 789 | /////CLICKWHEEL///// |
606 | #define WHEEL00 (*((uint32_t volatile*)(0x3C200000))) | 790 | #define WHEEL00 (*((uint32_t volatile*)(0x3C200000))) |
607 | #define WHEEL04 (*((uint32_t volatile*)(0x3C200004))) | 791 | #define WHEEL04 (*((uint32_t volatile*)(0x3C200004))) |
@@ -638,6 +822,8 @@ struct dma_lli | |||
638 | #define IRQ_DMAC1 17 | 822 | #define IRQ_DMAC1 17 |
639 | #define IRQ_WHEEL 23 | 823 | #define IRQ_WHEEL 23 |
640 | #define IRQ_ATA 29 | 824 | #define IRQ_ATA 29 |
825 | #define IRQ_MMC 44 | ||
641 | 826 | ||
642 | 827 | ||
643 | #endif | 828 | #endif |
829 | |||
diff --git a/firmware/target/arm/s5l8700/app.lds b/firmware/target/arm/s5l8700/app.lds index 2f8ef6a40f..aa37addbf6 100644 --- a/firmware/target/arm/s5l8700/app.lds +++ b/firmware/target/arm/s5l8700/app.lds | |||
@@ -100,7 +100,7 @@ SECTIONS | |||
100 | *(.stack) | 100 | *(.stack) |
101 | stackbegin = .; | 101 | stackbegin = .; |
102 | _stackbegin = .; | 102 | _stackbegin = .; |
103 | . += 0x4000; | 103 | . += 0x2000; |
104 | stackend = .; | 104 | stackend = .; |
105 | _stackend = .; | 105 | _stackend = .; |
106 | _irqstackbegin = .; | 106 | _irqstackbegin = .; |
diff --git a/firmware/target/arm/s5l8702/app.lds b/firmware/target/arm/s5l8702/app.lds index fafdea4cd9..ec66e5d969 100644 --- a/firmware/target/arm/s5l8702/app.lds +++ b/firmware/target/arm/s5l8702/app.lds | |||
@@ -95,7 +95,7 @@ SECTIONS | |||
95 | *(.stack) | 95 | *(.stack) |
96 | stackbegin = .; | 96 | stackbegin = .; |
97 | _stackbegin = .; | 97 | _stackbegin = .; |
98 | . += 0x4000; | 98 | . += 0x2000; |
99 | stackend = .; | 99 | stackend = .; |
100 | _stackend = .; | 100 | _stackend = .; |
101 | _irqstackbegin = .; | 101 | _irqstackbegin = .; |
diff --git a/firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c deleted file mode 100644 index f1577ee857..0000000000 --- a/firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c +++ /dev/null | |||
@@ -1,197 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: ata-meg-fx.c 27935 2010-08-28 23:12:11Z funman $ | ||
9 | * | ||
10 | * Copyright (C) 2011 by Michael Sparmann | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "config.h" | ||
22 | #include "cpu.h" | ||
23 | #include "kernel.h" | ||
24 | #include "thread.h" | ||
25 | #include "system.h" | ||
26 | #include "power.h" | ||
27 | #include "panic.h" | ||
28 | #include "pmu-target.h" | ||
29 | #include "ata.h" | ||
30 | #include "ata-target.h" | ||
31 | #include "s5l8702.h" | ||
32 | |||
33 | |||
34 | static struct wakeup ata_wakeup; | ||
35 | |||
36 | #ifdef HAVE_ATA_DMA | ||
37 | static uint32_t ata_dma_flags; | ||
38 | #endif | ||
39 | |||
40 | |||
41 | void ata_reset(void) | ||
42 | { | ||
43 | ATA_SWRST = 1; | ||
44 | sleep(HZ / 100); | ||
45 | ATA_SWRST = 0; | ||
46 | sleep(HZ / 10); | ||
47 | } | ||
48 | |||
49 | void ata_enable(bool on) | ||
50 | { | ||
51 | if (on) | ||
52 | { | ||
53 | PWRCON(0) &= ~(1 << 5); | ||
54 | ATA_CFG = 0x41; | ||
55 | sleep(HZ / 100); | ||
56 | ATA_CFG = 0x40; | ||
57 | sleep(HZ / 20); | ||
58 | ata_reset(); | ||
59 | ATA_CCONTROL = 1; | ||
60 | sleep(HZ / 5); | ||
61 | ATA_PIO_TIME = 0x191f7; | ||
62 | *ATA_HCYL = 0; | ||
63 | while (!(ATA_PIO_READY & 2)) yield(); | ||
64 | } | ||
65 | else | ||
66 | { | ||
67 | ATA_CCONTROL = 0; | ||
68 | while (!(ATA_CCONTROL & 2)) yield(); | ||
69 | PWRCON(1) |= 1 << 5; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | bool ata_is_coldstart(void) | ||
74 | { | ||
75 | return false; | ||
76 | } | ||
77 | |||
78 | void ata_device_init(void) | ||
79 | { | ||
80 | VIC0INTENABLE = 1 << IRQ_ATA; | ||
81 | } | ||
82 | |||
83 | uint16_t ata_read_cbr(uint32_t volatile* reg) | ||
84 | { | ||
85 | while (!(ATA_PIO_READY & 2)); | ||
86 | volatile uint32_t __attribute__((unused)) dummy = *reg; | ||
87 | while (!(ATA_PIO_READY & 1)); | ||
88 | return ATA_PIO_RDATA; | ||
89 | } | ||
90 | |||
91 | void ata_write_cbr(uint32_t volatile* reg, uint16_t data) | ||
92 | { | ||
93 | while (!(ATA_PIO_READY & 2)); | ||
94 | *reg = data; | ||
95 | } | ||
96 | |||
97 | void ata_set_pio_timings(int mode) | ||
98 | { | ||
99 | if (mode >= 4) ATA_PIO_TIME = 0x7083; | ||
100 | if (mode >= 3) ATA_PIO_TIME = 0x2072; | ||
101 | else ATA_PIO_TIME = 0x11f3; | ||
102 | } | ||
103 | |||
104 | #ifdef HAVE_ATA_DMA | ||
105 | static void ata_set_mdma_timings(unsigned int mode) | ||
106 | { | ||
107 | if (mode >= 2) ATA_MDMA_TIME = 0x5072; | ||
108 | if (mode >= 1) ATA_MDMA_TIME = 0x7083; | ||
109 | else ATA_MDMA_TIME = 0x1c175; | ||
110 | } | ||
111 | |||
112 | static void ata_set_udma_timings(unsigned int mode) | ||
113 | { | ||
114 | if (mode >= 4) ATA_UDMA_TIME = 0x2010a52; | ||
115 | if (mode >= 3) ATA_UDMA_TIME = 0x2020a52; | ||
116 | if (mode >= 2) ATA_UDMA_TIME = 0x3030a52; | ||
117 | if (mode >= 1) ATA_UDMA_TIME = 0x3050a52; | ||
118 | else ATA_UDMA_TIME = 0x5071152; | ||
119 | } | ||
120 | |||
121 | void ata_dma_set_mode(unsigned char mode) | ||
122 | { | ||
123 | unsigned int modeidx = mode & 0x07; | ||
124 | unsigned int dmamode = mode & 0xf8; | ||
125 | |||
126 | if (dmamode == 0x40 && modeidx <= ATA_MAX_UDMA) | ||
127 | { | ||
128 | /* Using Ultra DMA */ | ||
129 | ata_set_udma_timings(dmamode); | ||
130 | ata_dma_flags = 0x60c; | ||
131 | } | ||
132 | else if (dmamode == 0x20 && modeidx <= ATA_MAX_MWDMA) | ||
133 | { | ||
134 | /* Using Multiword DMA */ | ||
135 | ata_set_mdma_timings(dmamode); | ||
136 | ata_dma_flags = 0x408; | ||
137 | } | ||
138 | else | ||
139 | { | ||
140 | /* Don't understand this - force PIO. */ | ||
141 | ata_dma_flags = 0; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | bool ata_dma_setup(void *addr, unsigned long bytes, bool write) | ||
146 | { | ||
147 | if ((((int)addr) & 0xf) || (((int)bytes) & 0xf) || !ata_dma_flags) | ||
148 | return false; | ||
149 | |||
150 | if (write) clean_dcache(); | ||
151 | else invalidate_dcache(); | ||
152 | ATA_CCOMMAND = 2; | ||
153 | |||
154 | if (write) | ||
155 | { | ||
156 | ATA_SBUF_START = addr; | ||
157 | ATA_SBUF_SIZE = bytes; | ||
158 | ATA_CFG |= 0x10; | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | ATA_TBUF_START = addr; | ||
163 | ATA_TBUF_SIZE = bytes; | ||
164 | ATA_CFG &= ~0x10; | ||
165 | } | ||
166 | ATA_XFR_NUM = bytes - 1; | ||
167 | |||
168 | return true; | ||
169 | } | ||
170 | |||
171 | bool ata_dma_finish(void) | ||
172 | { | ||
173 | ATA_CFG |= ata_dma_flags; | ||
174 | ATA_CFG &= ~0x180; | ||
175 | wakeup_wait(&ata_wakeup, TIMEOUT_NOBLOCK); | ||
176 | ATA_IRQ = 0x1f; | ||
177 | ATA_IRQ_MASK = 1; | ||
178 | ATA_CCOMMAND = 1; | ||
179 | if (wakeup_wait(&ata_wakeup, HZ / 2) != OBJ_WAIT_SUCCEEDED) | ||
180 | { | ||
181 | ATA_CCOMMAND = 2; | ||
182 | ATA_CFG &= ~0x100c; | ||
183 | return false; | ||
184 | } | ||
185 | ATA_CCOMMAND = 2; | ||
186 | ATA_CFG &= ~0x100c; | ||
187 | return true; | ||
188 | } | ||
189 | #endif /* HAVE_ATA_DMA */ | ||
190 | |||
191 | void INT_ATA(void) | ||
192 | { | ||
193 | uint32_t ata_irq = ATA_IRQ; | ||
194 | ATA_IRQ = ata_irq; | ||
195 | if (ata_irq & ATA_IRQ_MASK) wakeup_signal(&ata_wakeup); | ||
196 | ATA_IRQ_MASK = 0; | ||
197 | } | ||
diff --git a/firmware/target/arm/s5l8702/ipod6g/ata-target.h b/firmware/target/arm/s5l8702/ipod6g/ata-target.h deleted file mode 100644 index e2e7bd298c..0000000000 --- a/firmware/target/arm/s5l8702/ipod6g/ata-target.h +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: ata-target.h 25525 2010-04-07 20:01:21Z torne $ | ||
9 | * | ||
10 | * Copyright (C) 2011 by Michael Sparmann | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #ifndef ATA_TARGET_H | ||
22 | #define ATA_TARGET_H | ||
23 | |||
24 | #include "inttypes.h" | ||
25 | #include "s5l8702.h" | ||
26 | |||
27 | #ifdef BOOTLOADER | ||
28 | #define ATA_DRIVER_CLOSE | ||
29 | #endif | ||
30 | |||
31 | #define ATA_SWAP_IDENTIFY(word) (swap16(word)) | ||
32 | |||
33 | void ata_reset(void); | ||
34 | void ata_device_init(void); | ||
35 | bool ata_is_coldstart(void); | ||
36 | uint16_t ata_read_cbr(uint32_t volatile* reg); | ||
37 | void ata_write_cbr(uint32_t volatile* reg, uint16_t data); | ||
38 | |||
39 | #define ATA_OUT8(reg, data) ata_write_cbr(reg, data) | ||
40 | #define ATA_OUT16(reg, data) ata_write_cbr(reg, data) | ||
41 | #define ATA_IN8(reg) ata_read_cbr(reg) | ||
42 | #define ATA_IN16(reg) ata_read_cbr(reg) | ||
43 | |||
44 | #define ATA_SET_DEVICE_FEATURES | ||
45 | void ata_set_pio_timings(int mode); | ||
46 | |||
47 | #endif | ||
diff --git a/firmware/target/arm/s5l8702/ipod6g/mmcdefs-target.h b/firmware/target/arm/s5l8702/ipod6g/mmcdefs-target.h new file mode 100644 index 0000000000..50e591253e --- /dev/null +++ b/firmware/target/arm/s5l8702/ipod6g/mmcdefs-target.h | |||
@@ -0,0 +1,345 @@ | |||
1 | // | ||
2 | // | ||
3 | // Copyright 2010 TheSeven | ||
4 | // | ||
5 | // | ||
6 | // This file is part of emCORE. | ||
7 | // | ||
8 | // emCORE is free software: you can redistribute it and/or | ||
9 | // modify it under the terms of the GNU General Public License as | ||
10 | // published by the Free Software Foundation, either version 2 of the | ||
11 | // License, or (at your option) any later version. | ||
12 | // | ||
13 | // emCORE is distributed in the hope that it will be useful, | ||
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
16 | // See the GNU General Public License for more details. | ||
17 | // | ||
18 | // You should have received a copy of the GNU General Public License along | ||
19 | // with emCORE. If not, see <http://www.gnu.org/licenses/>. | ||
20 | // | ||
21 | // | ||
22 | |||
23 | |||
24 | #ifndef __CONSTANTS_MMC_H__ | ||
25 | #define __CONSTANTS_MMC_H__ | ||
26 | |||
27 | |||
28 | #ifndef MIN | ||
29 | #define MIN(a, b) (((a)<(b))?(a):(b)) | ||
30 | #endif | ||
31 | |||
32 | #ifndef MAX | ||
33 | #define MAX(a, b) (((a)>(b))?(a):(b)) | ||
34 | #endif | ||
35 | |||
36 | #define BIT(x) (1 << (x)) | ||
37 | #define BITRANGE(x, y) ((0xfffffffful >> (31 + (x) - (y))) << (x)) | ||
38 | |||
39 | #define ERR_RC(val) (BIT(31) | (val)) | ||
40 | #define IS_ERR(val) (val & BIT(31)) | ||
41 | #define RET_ERR(val) \ | ||
42 | { \ | ||
43 | return ERR_RC(val); \ | ||
44 | } | ||
45 | #define RET_ERR_MTX(val, mutex) \ | ||
46 | { \ | ||
47 | mutex_unlock(mutex); \ | ||
48 | return ERR_RC(val); \ | ||
49 | } | ||
50 | #define PASS_RC(expr, bits, val) \ | ||
51 | { \ | ||
52 | int PASS_RC_rc = (expr); \ | ||
53 | if (IS_ERR(PASS_RC_rc)) \ | ||
54 | return ERR_RC((PASS_RC_rc << (bits)) | (val)); \ | ||
55 | } | ||
56 | #define PASS_RC_MTX(expr, bits, val, mutex) \ | ||
57 | { \ | ||
58 | int PASS_RC_MTX_rc = (expr); \ | ||
59 | if (IS_ERR(PASS_RC_MTX_rc)) \ | ||
60 | { \ | ||
61 | mutex_unlock(mutex); \ | ||
62 | return ERR_RC((PASS_RC_MTX_rc << (bits)) | (val)); \ | ||
63 | } \ | ||
64 | } | ||
65 | |||
66 | #define TIMEOUT_EXPIRED(a,b) TIME_AFTER(USEC_TIMER,a + b) | ||
67 | #define udelay(duration) \ | ||
68 | { \ | ||
69 | long timestamp = USEC_TIMER; \ | ||
70 | while (!TIMEOUT_EXPIRED(timestamp, (long)(duration))); \ | ||
71 | } | ||
72 | |||
73 | |||
74 | #define MMC_CMD_GO_IDLE_STATE 0 | ||
75 | #define MMC_CMD_SEND_OP_COND 1 | ||
76 | #define MMC_CMD_ALL_SEND_CID 2 | ||
77 | #define MMC_CMD_SET_RELATIVE_ADDR 3 | ||
78 | #define MMC_CMD_SET_DSR 4 | ||
79 | #define MMC_CMD_SLEEP_AWAKE 5 | ||
80 | #define MMC_CMD_SWITCH 6 | ||
81 | #define MMC_CMD_SELECT_CARD 7 | ||
82 | #define MMC_CMD_SEND_EXT_CSD 8 | ||
83 | #define MMC_CMD_SEND_CSD 9 | ||
84 | #define MMC_CMD_SEND_CID 10 | ||
85 | #define MMC_CMD_READ_DAT_UNTIL_STOP 11 | ||
86 | #define MMC_CMD_STOP_TRANSMISSION 12 | ||
87 | #define MMC_CMD_SEND_STATUS 13 | ||
88 | #define MMC_CMD_BUSTEST_R 14 | ||
89 | #define MMC_CMD_GO_INAVTIVE_STATE 15 | ||
90 | #define MMC_CMD_SET_BLOCKLEN 16 | ||
91 | #define MMC_CMD_READ_SINGLE_BLOCK 17 | ||
92 | #define MMC_CMD_READ_MULTIPLE_BLOCK 18 | ||
93 | #define MMC_CMD_BUSTEST_W 19 | ||
94 | #define MMC_CMD_WRITE_DAT_UNTIL_STOP 20 | ||
95 | #define MMC_CMD_SET_BLOCK_COUNT 23 | ||
96 | #define MMC_CMD_WRITE_BLOCK 24 | ||
97 | #define MMC_CMD_WRITE_MULTIPLE_BLOCK 25 | ||
98 | #define MMC_CMD_PROGRAM_CID 26 | ||
99 | #define MMC_CMD_PROGRAM_CSD 27 | ||
100 | #define MMC_CMD_SET_WRITE_PROT 28 | ||
101 | #define MMC_CMD_CLR_WRITE_PROT 29 | ||
102 | #define MMC_CMD_SEND_WRITE_PROT 30 | ||
103 | #define MMC_CMD_ERASE_GROUP_START 35 | ||
104 | #define MMC_CMD_ERASE_GROUP_END 36 | ||
105 | #define MMC_CMD_ERASE 38 | ||
106 | #define MMC_CMD_FAST_IO 39 | ||
107 | #define MMC_CMD_GO_IRQ_STATE 40 | ||
108 | #define MMC_CMD_LOCK_UNLOCK 42 | ||
109 | #define MMC_CMD_APP_CMD 55 | ||
110 | #define MMC_CMD_GEN_CMD 56 | ||
111 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG 60 | ||
112 | #define MMC_CMD_CEATA_RW_MULTIPLE_BLOCK 61 | ||
113 | |||
114 | #define MMC_CMD_SEND_OP_COND_OCR_MASK BITRANGE(0, 31) | ||
115 | #define MMC_CMD_SEND_OP_COND_OCR_SHIFT 0 | ||
116 | #define MMC_CMD_SEND_OP_COND_OCR(x) (x) | ||
117 | |||
118 | #define MMC_CMD_SET_RELATIVE_ADDR_RCA_MASK BITRANGE(16, 31) | ||
119 | #define MMC_CMD_SET_RELATIVE_ADDR_RCA_SHIFT 16 | ||
120 | #define MMC_CMD_SET_RELATIVE_ADDR_RCA(x) ((x) << 16) | ||
121 | |||
122 | #define MMC_CMD_SET_DSR_DSR_MASK BITRANGE(16, 31) | ||
123 | #define MMC_CMD_SET_DSR_DSR_SHIFT 16 | ||
124 | #define MMC_CMD_SET_DSR_DSR(x) ((x) << 16) | ||
125 | |||
126 | #define MMC_CMD_SLEEP_AWAKE_SLEEP_AWAKE_MASK BIT(15) | ||
127 | #define MMC_CMD_SLEEP_AWAKE_SLEEP_AWAKE_AWAKE 0 | ||
128 | #define MMC_CMD_SLEEP_AWAKE_SLEEP_AWAKE_SLEEP BIT(15) | ||
129 | #define MMC_CMD_SLEEP_AWAKE_RCA_MASK BITRANGE(16, 31) | ||
130 | #define MMC_CMD_SLEEP_AWAKE_RCA_SHIFT 16 | ||
131 | #define MMC_CMD_SLEEP_AWAKE_RCA(x) ((x) << 16) | ||
132 | |||
133 | #define MMC_CMD_SWITCH_ACCESS_MASK BITRANGE(24, 25); | ||
134 | #define MMC_CMD_SWITCH_ACCESS_CMDSET 0 | ||
135 | #define MMC_CMD_SWITCH_ACCESS_SET_BITS BIT(24) | ||
136 | #define MMC_CMD_SWITCH_ACCESS_CLEAR_BITS BIT(25) | ||
137 | #define MMC_CMD_SWITCH_ACCESS_WRITE_BYTE (BIT(24) | BIT(25)) | ||
138 | #define MMC_CMD_SWTICH_INDEX_MASK BITRANGE(16, 23); | ||
139 | #define MMC_CMD_SWITCH_INDEX_SHIFT 16 | ||
140 | #define MMC_CMD_SWITCH_INDEX(x) ((x) << 16) | ||
141 | #define MMC_CMD_SWTICH_VALUE_MASK BITRANGE(8, 15); | ||
142 | #define MMC_CMD_SWITCH_VALUE_SHIFT 8 | ||
143 | #define MMC_CMD_SWITCH_VALUE(x) ((x) << 8) | ||
144 | #define MMC_CMD_SWTICH_CMDSET_MASK BITRANGE(0, 2); | ||
145 | #define MMC_CMD_SWITCH_CMDSET_STANDARD_MMC 0 | ||
146 | |||
147 | #define MMC_CMD_SELECT_CARD_RCA_MASK BITRANGE(16, 31) | ||
148 | #define MMC_CMD_SELECT_CARD_RCA_SHIFT 16 | ||
149 | #define MMC_CMD_SELECT_CARD_RCA(x) ((x) << 16) | ||
150 | |||
151 | #define MMC_CMD_SEND_CSD_RCA_MASK BITRANGE(16, 31) | ||
152 | #define MMC_CMD_SEND_CSD_RCA_SHIFT 16 | ||
153 | #define MMC_CMD_SEND_CSD_RCA(x) ((x) << 16) | ||
154 | |||
155 | #define MMC_CMD_SEND_CID_RCA_MASK BITRANGE(16, 31) | ||
156 | #define MMC_CMD_SEND_CID_RCA_SHIFT 16 | ||
157 | #define MMC_CMD_SEND_CID_RCA(x) ((x) << 16) | ||
158 | |||
159 | #define MMC_CMD_READ_DAT_UNTIL_STOP_ADDRESS_MASK BITRANGE(0, 31) | ||
160 | #define MMC_CMD_READ_DAT_UNTIL_STOP_ADDRESS_SHIFT 0 | ||
161 | #define MMC_CMD_READ_DAT_UNTIL_STOP_ADDRESS(x) (x) | ||
162 | |||
163 | #define MMC_CMD_SEND_STATUS_RCA_MASK BITRANGE(16, 31) | ||
164 | #define MMC_CMD_SEND_STATUS_RCA_SHIFT 16 | ||
165 | #define MMC_CMD_SEND_STATUS_RCA(x) ((x) << 16) | ||
166 | |||
167 | #define MMC_CMD_GO_INACTIVE_STATE_RCA_MASK BITRANGE(16, 31) | ||
168 | #define MMC_CMD_GO_INACTIVE_STATE_RCA_SHIFT 16 | ||
169 | #define MMC_CMD_GO_INACTIVE_STATE_RCA(x) ((x) << 16) | ||
170 | |||
171 | #define MMC_CMD_SET_BLOCKLEN_LENGTH_MASK BITRANGE(0, 31) | ||
172 | #define MMC_CMD_SET_BLOCKLEN_LENGTH_SHIFT 0 | ||
173 | #define MMC_CMD_SET_BLOCKLEN_LENGTH(x) (x) | ||
174 | |||
175 | #define MMC_CMD_READ_SINGLE_BLOCK_ADDRESS_MASK BITRANGE(0, 31) | ||
176 | #define MMC_CMD_READ_SINGLE_BLOCK_ADDRESS_SHIFT 0 | ||
177 | #define MMC_CMD_READ_SINGLE_BLOCK_ADDRESS(x) (x) | ||
178 | |||
179 | #define MMC_CMD_READ_MULTIPLE_BLOCK_ADDRESS_MASK BITRANGE(0, 31) | ||
180 | #define MMC_CMD_READ_MULTIPLE_BLOCK_ADDRESS_SHIFT 0 | ||
181 | #define MMC_CMD_READ_MULTIPLE_BLOCK_ADDRESS(x) (x) | ||
182 | |||
183 | #define MMC_CMD_WRITE_DAT_UNTIL_STOP_ADDRESS_MASK BITRANGE(0, 31) | ||
184 | #define MMC_CMD_WRITE_DAT_UNTIL_STOP_ADDRESS_SHIFT 0 | ||
185 | #define MMC_CMD_WRITE_DAT_UNTIL_STOP_ADDRESS(x) (x) | ||
186 | |||
187 | #define MMC_CMD_SET_BLOCK_COUNT_RELIABLE BIT(31) | ||
188 | #define MMC_CMD_SET_BLOCK_COUNT_COUNT_MASK BITRANGE(0, 15) | ||
189 | #define MMC_CMD_SET_BLOCK_COUNT_COUNT_SHIFT 0 | ||
190 | #define MMC_CMD_SET_BLOCK_COUNT_COUNT(x) (x) | ||
191 | |||
192 | #define MMC_CMD_WRITE_BLOCK_ADDRESS_MASK BITRANGE(0, 31) | ||
193 | #define MMC_CMD_WRITE_BLOCK_ADDRESS_SHIFT 0 | ||
194 | #define MMC_CMD_WRITE_BLOCK_ADDRESS(x) (x) | ||
195 | |||
196 | #define MMC_CMD_WRITE_MULTIPLE_BLOCK_ADDRESS_MASK BITRANGE(0, 31) | ||
197 | #define MMC_CMD_WRITE_MULTIPLE_BLOCK_ADDRESS_SHIFT 0 | ||
198 | #define MMC_CMD_WRITE_MULTIPLE_BLOCK_ADDRESS(x) (x) | ||
199 | |||
200 | #define MMC_CMD_SET_WRITE_PROT_ADDRESS_MASK BITRANGE(0, 31) | ||
201 | #define MMC_CMD_SET_WRITE_PROT_ADDRESS_SHIFT 0 | ||
202 | #define MMC_CMD_SET_WRITE_PROT_ADDRESS(x) (x) | ||
203 | |||
204 | #define MMC_CMD_CLR_WRITE_PROT_ADDRESS_MASK BITRANGE(0, 31) | ||
205 | #define MMC_CMD_CLR_WRITE_PROT_ADDRESS_SHIFT 0 | ||
206 | #define MMC_CMD_CLR_WRITE_PROT_ADDRESS(x) (x) | ||
207 | |||
208 | #define MMC_CMD_SEND_WRITE_PROT_ADDRESS_MASK BITRANGE(0, 31) | ||
209 | #define MMC_CMD_SEND_WRITE_PROT_ADDRESS_SHIFT 0 | ||
210 | #define MMC_CMD_SEND_WRITE_PROT_ADDRESS(x) (x) | ||
211 | |||
212 | #define MMC_CMD_ERASE_GROUP_START_ADDRESS_MASK BITRANGE(0, 31) | ||
213 | #define MMC_CMD_ERASE_GROUP_START_ADDRESS_SHIFT 0 | ||
214 | #define MMC_CMD_ERASE_GROUP_START_ADDRESS(x) (x) | ||
215 | |||
216 | #define MMC_CMD_ERASE_GROUP_END_ADDRESS_MASK BITRANGE(0, 31) | ||
217 | #define MMC_CMD_ERASE_GROUP_END_ADDRESS_SHIFT 0 | ||
218 | #define MMC_CMD_ERASE_GROUP_END_ADDRESS(x) (x) | ||
219 | |||
220 | #define MMC_CMD_FAST_IO_RCA_MASK BITRANGE(16, 31) | ||
221 | #define MMC_CMD_FAST_IO_RCA_SHIFT 16 | ||
222 | #define MMC_CMD_FAST_IO_RCA(x) ((x) << 16) | ||
223 | #define MMC_CMD_FAST_IO_DIRECTION_MASK BIT(15) | ||
224 | #define MMC_CMD_FAST_IO_DIRECTION_READ 0 | ||
225 | #define MMC_CMD_FAST_IO_DIRECTION_WRITE BIT(15) | ||
226 | #define MMC_CMD_FAST_IO_ADDRESS_MASK BITRANGE(8, 14) | ||
227 | #define MMC_CMD_FAST_IO_ADDRESS_SHIFT 8 | ||
228 | #define MMC_CMD_FAST_IO_ADDRESS(x) ((x) << 8) | ||
229 | #define MMC_CMD_FAST_IO_DATA_MASK BITRANGE(0, 7) | ||
230 | #define MMC_CMD_FAST_IO_DATA_SHIFT 0 | ||
231 | #define MMC_CMD_FAST_IO_DATA(x) (x) | ||
232 | |||
233 | #define MMC_CMD_APP_CMD_RCA_MASK BITRANGE(16, 31) | ||
234 | #define MMC_CMD_APP_CMD_RCA_SHIFT 16 | ||
235 | #define MMC_CMD_APP_CMD_RCA(x) ((x) << 16) | ||
236 | |||
237 | #define MMC_CMD_GEN_CMD_DIRECTION_MASK BIT(0) | ||
238 | #define MMC_CMD_GEN_CMD_DIRECTION_READ 0 | ||
239 | #define MMC_CMD_GEN_CMD_DIRECTION_WRITE BIT(0) | ||
240 | |||
241 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG_DIRECTION_MASK BIT(31) | ||
242 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG_DIRECTION_READ 0 | ||
243 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG_DIRECTION_WRITE BIT(31) | ||
244 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS_MASK BITRANGE(16, 23) | ||
245 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS_SHIFT 16 | ||
246 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS(x) ((x) << 16) | ||
247 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT_MASK BITRANGE(0, 7) | ||
248 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT_SHIFT 0 | ||
249 | #define MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(x) (x) | ||
250 | |||
251 | #define MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_DIRECTION_MASK BIT(31) | ||
252 | #define MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_DIRECTION_READ 0 | ||
253 | #define MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_DIRECTION_WRITE BIT(31) | ||
254 | #define MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT_MASK BITRANGE(0, 15) | ||
255 | #define MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT_SHIFT 0 | ||
256 | #define MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT(x) (x) | ||
257 | |||
258 | #define MMC_CMD_SWITCH_FIELD_ERASE_GROUP_DEF 175 | ||
259 | #define MMC_CMD_SWITCH_FIELD_BOOT_BUS_WIDTH 177 | ||
260 | #define MMC_CMD_SWITCH_FIELD_BOOT_CONFIG 179 | ||
261 | #define MMC_CMD_SWITCH_FIELD_ERASED_MEM_CONT 181 | ||
262 | #define MMC_CMD_SWITCH_FIELD_BUS_WIDTH 183 | ||
263 | #define MMC_CMD_SWITCH_FIELD_HS_TIMING 185 | ||
264 | #define MMC_CMD_SWITCH_FIELD_POWER_CLASS 187 | ||
265 | #define MMC_CMD_SWITCH_FIELD_CMD_SET_REV 189 | ||
266 | #define MMC_CMD_SWITCH_FIELD_CMD_SET 191 | ||
267 | #define MMC_CMD_SWITCH_FIELD_EXT_CSD_REV 192 | ||
268 | #define MMC_CMD_SWITCH_FIELD_CSD_STRUCTURE 194 | ||
269 | #define MMC_CMD_SWITCH_FIELD_CARD_TYPE 196 | ||
270 | #define MMC_CMD_SWITCH_FIELD_PWR_CL_52_195 200 | ||
271 | #define MMC_CMD_SWITCH_FIELD_PWR_CL_26_195 201 | ||
272 | #define MMC_CMD_SWITCH_FIELD_PWR_CL_52_360 202 | ||
273 | #define MMC_CMD_SWITCH_FIELD_PWR_CL_26_360 203 | ||
274 | #define MMC_CMD_SWITCH_FIELD_MIN_PERF_R_4_26 205 | ||
275 | #define MMC_CMD_SWITCH_FIELD_MIN_PERF_W_4_26 206 | ||
276 | #define MMC_CMD_SWITCH_FIELD_MIN_PERF_R_8_26_4_52 207 | ||
277 | #define MMC_CMD_SWITCH_FIELD_MIN_PERF_W_8_26_4_52 208 | ||
278 | #define MMC_CMD_SWITCH_FIELD_MIN_PERF_R_8_52 209 | ||
279 | #define MMC_CMD_SWITCH_FIELD_MIN_PERF_W_8_52 210 | ||
280 | #define MMC_CMD_SWITCH_FIELD_SEC_COUNT_0 212 | ||
281 | #define MMC_CMD_SWITCH_FIELD_SEC_COUNT_1 213 | ||
282 | #define MMC_CMD_SWITCH_FIELD_SEC_COUNT_2 214 | ||
283 | #define MMC_CMD_SWITCH_FIELD_SEC_COUNT_3 215 | ||
284 | #define MMC_CMD_SWITCH_FIELD_S_A_TIMEOUT 217 | ||
285 | #define MMC_CMD_SWITCH_FIELD_S_C_VCCQ 219 | ||
286 | #define MMC_CMD_SWITCH_FIELD_S_C_VCC 220 | ||
287 | #define MMC_CMD_SWITCH_FIELD_HC_WP_GRP_SIZE 221 | ||
288 | #define MMC_CMD_SWITCH_FIELD_REL_WR_SEC_C 222 | ||
289 | #define MMC_CMD_SWITCH_FIELD_ERASE_TIMEOUT_MULT 223 | ||
290 | #define MMC_CMD_SWITCH_FIELD_HC_ERASE_GRP_SIZE 224 | ||
291 | #define MMC_CMD_SWITCH_FIELD_ACC_SIZE 225 | ||
292 | #define MMC_CMD_SWITCH_FIELD_BOOT_SIZE_MULTI 226 | ||
293 | #define MMC_CMD_SWITCH_FIELD_S_CMD_SET 504 | ||
294 | |||
295 | #define MMC_CMD_SWITCH_FIELD_BUS_WIDTH_1BIT 0 | ||
296 | #define MMC_CMD_SWITCH_FIELD_BUS_WIDTH_4BIT 1 | ||
297 | #define MMC_CMD_SWITCH_FIELD_BUS_WIDTH_8BIT 2 | ||
298 | |||
299 | #define MMC_CMD_SWITCH_FIELD_HS_TIMING_LOW_SPEED 0 | ||
300 | #define MMC_CMD_SWITCH_FIELD_HS_TIMING_HIGH_SPEED 1 | ||
301 | |||
302 | #define MMC_STATUS_APP_CMD BIT(5) | ||
303 | #define MMC_STATUS_SWITCH_ERROR BIT(7) | ||
304 | #define MMC_STATUS_READY_FOR_DATA BIT(8) | ||
305 | #define MMC_STATUS_CURRENT_STATE_MASK BITRANGE(9, 12) | ||
306 | #define MMC_STATUS_CURRENT_STATE_IDLE 0 | ||
307 | #define MMC_STATUS_CURRENT_STATE_READY BIT(9) | ||
308 | #define MMC_STATUS_CURRENT_STATE_IDENT BIT(10) | ||
309 | #define MMC_STATUS_CURRENT_STATE_STBY (BIT(9) | BIT(10)) | ||
310 | #define MMC_STATUS_CURRENT_STATE_TRAN BIT(11) | ||
311 | #define MMC_STATUS_CURRENT_STATE_DATA (BIT(9) | BIT(11)) | ||
312 | #define MMC_STATUS_CURRENT_STATE_RCV (BIT(10) | BIT(11)) | ||
313 | #define MMC_STATUS_CURRENT_STATE_PRG (BIT(9) | BIT(10) | BIT(11)) | ||
314 | #define MMC_STATUS_CURRENT_STATE_DIS BIT(12) | ||
315 | #define MMC_STATUS_CURRENT_STATE_BTST (BIT(9) | BIT(12)) | ||
316 | #define MMC_STATUS_CURRENT_STATE_SLP (BIT(10) | BIT(12)) | ||
317 | #define MMC_STATUS_ERASE_RESET BIT(13) | ||
318 | #define MMC_STATUS_WP_ERASE_SKIP BIT(15) | ||
319 | #define MMC_STATUS_CID_CSD_OVERWRITE BIT(16) | ||
320 | #define MMC_STATUS_OVERRUN BIT(17) | ||
321 | #define MMC_STATUS_UNDERRUN BIT(18) | ||
322 | #define MMC_STATUS_ERROR BIT(19) | ||
323 | #define MMC_STATUS_CC_ERROR BIT(20) | ||
324 | #define MMC_STATUS_CARD_ECC_FAILED BIT(21) | ||
325 | #define MMC_STATUS_ILLEGAL_COMMAND BIT(22) | ||
326 | #define MMC_STATUS_COM_CRC_ERROR BIT(23) | ||
327 | #define MMC_STATUS_LOCK_UNLOCK_FAILED BIT(24) | ||
328 | #define MMC_STATUS_CARD_IS_LOCKED BIT(25) | ||
329 | #define MMC_STATUS_WP_VIOLATION BIT(26) | ||
330 | #define MMC_STATUS_ERASE_PARAM BIT(27) | ||
331 | #define MMC_STATUS_ERASE_SEQ_ERROR BIT(28) | ||
332 | #define MMC_STATUS_BLOCK_LEN_ERROR BIT(29) | ||
333 | #define MMC_STATUS_ADDRESS_MISALIGN BIT(30) | ||
334 | #define MMC_STATUS_ADDRESS_OUT_OF_RANGE BIT(31) | ||
335 | |||
336 | #define MMC_OCR_170_195 BIT(7) | ||
337 | #define MMC_OCR_200_260 BITRANGE(8, 14) | ||
338 | #define MMC_OCR_270_360 BITRANGE(15, 23) | ||
339 | #define MMC_OCR_ACCESS_MODE_MASK BITRANGE(29, 30) | ||
340 | #define MMC_OCR_ACCESS_MODE_BYTE 0 | ||
341 | #define MMC_OCR_ACCESS_MODE_SECTOR BIT(30) | ||
342 | #define MMC_OCR_POWER_UP_DONE BIT(31) | ||
343 | |||
344 | |||
345 | #endif | ||
diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c new file mode 100644 index 0000000000..66e02d65bb --- /dev/null +++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-ipod6g.c | |||
@@ -0,0 +1,1142 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 Dave Chapman | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "config.h" | ||
22 | #include "thread.h" | ||
23 | #include "disk.h" | ||
24 | #include "storage.h" | ||
25 | #include "timer.h" | ||
26 | #include "kernel.h" | ||
27 | #include "string.h" | ||
28 | #include "power.h" | ||
29 | #include "panic.h" | ||
30 | #include "mmu-arm.h" | ||
31 | #include "mmcdefs-target.h" | ||
32 | #include "s5l8702.h" | ||
33 | #include "led.h" | ||
34 | #include "ata_idle_notify.h" | ||
35 | |||
36 | |||
37 | #ifndef ATA_RETRIES | ||
38 | #define ATA_RETRIES 3 | ||
39 | #endif | ||
40 | |||
41 | |||
42 | #define CEATA_POWERUP_TIMEOUT 20000000 | ||
43 | #define CEATA_COMMAND_TIMEOUT 1000000 | ||
44 | #define CEATA_DAT_NONBUSY_TIMEOUT 5000000 | ||
45 | #define CEATA_MMC_RCA 1 | ||
46 | |||
47 | |||
48 | /** static, private data **/ | ||
49 | static uint8_t ceata_taskfile[16] __attribute__((aligned(16))); | ||
50 | uint16_t ata_identify_data[0x100] __attribute__((aligned(16))); | ||
51 | bool ceata; | ||
52 | bool ata_lba48; | ||
53 | bool ata_dma; | ||
54 | uint64_t ata_total_sectors; | ||
55 | struct mutex ata_mutex; | ||
56 | static struct wakeup ata_wakeup; | ||
57 | static uint32_t ata_dma_flags; | ||
58 | static long ata_last_activity_value = -1; | ||
59 | static long ata_sleep_timeout = 20 * HZ; | ||
60 | static uint32_t ata_stack[(DEFAULT_STACK_SIZE + 0x400) / 4]; | ||
61 | static bool ata_powered; | ||
62 | static const int ata_retries = ATA_RETRIES; | ||
63 | static const bool ata_error_srst = true; | ||
64 | static struct wakeup mmc_wakeup; | ||
65 | static struct wakeup mmc_comp_wakeup; | ||
66 | static int spinup_time = 0; | ||
67 | static int dma_mode = 0; | ||
68 | |||
69 | |||
70 | #ifdef ATA_HAVE_BBT | ||
71 | char ata_bbtbuf[ATA_BBT_PAGES * 64]; | ||
72 | uint16_t (*ata_bbt)[0x20]; | ||
73 | uint64_t ata_virtual_sectors; | ||
74 | uint32_t ata_last_offset; | ||
75 | uint64_t ata_last_phys; | ||
76 | |||
77 | int ata_bbt_read_sectors(uint32_t sector, uint32_t count, void* buffer) | ||
78 | { | ||
79 | if (ata_last_phys != sector - 1 && ata_last_phys > sector - 64) ata_soft_reset(); | ||
80 | int rc = ata_rw_sectors_internal(sector, count, buffer, false); | ||
81 | if (rc) rc = ata_rw_sectors_internal(sector, count, buffer, false); | ||
82 | ata_last_phys = sector + count - 1; | ||
83 | ata_last_offset = 0; | ||
84 | if (IS_ERR(rc)) | ||
85 | panicf("ATA: Error %08X while reading BBT (sector %d, count %d)\n", | ||
86 | rc, sector, count); | ||
87 | return rc; | ||
88 | } | ||
89 | #endif | ||
90 | |||
91 | |||
92 | static uint16_t ata_read_cbr(uint32_t volatile* reg) | ||
93 | { | ||
94 | while (!(ATA_PIO_READY & 2)); | ||
95 | volatile uint32_t dummy __attribute__((unused)) = *reg; | ||
96 | while (!(ATA_PIO_READY & 1)); | ||
97 | return ATA_PIO_RDATA; | ||
98 | } | ||
99 | |||
100 | static void ata_write_cbr(uint32_t volatile* reg, uint16_t data) | ||
101 | { | ||
102 | while (!(ATA_PIO_READY & 2)); | ||
103 | *reg = data; | ||
104 | } | ||
105 | |||
106 | static int ata_wait_for_not_bsy(long timeout) | ||
107 | { | ||
108 | long startusec = USEC_TIMER; | ||
109 | while (true) | ||
110 | { | ||
111 | uint8_t csd = ata_read_cbr(&ATA_PIO_CSD); | ||
112 | if (!(csd & BIT(7))) return 0; | ||
113 | if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(0); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | static int ata_wait_for_rdy(long timeout) | ||
118 | { | ||
119 | long startusec = USEC_TIMER; | ||
120 | PASS_RC(ata_wait_for_not_bsy(timeout), 1, 0); | ||
121 | while (true) | ||
122 | { | ||
123 | uint8_t dad = ata_read_cbr(&ATA_PIO_DAD); | ||
124 | if (dad & BIT(6)) return 0; | ||
125 | if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(1); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static int ata_wait_for_start_of_transfer(long timeout) | ||
130 | { | ||
131 | long startusec = USEC_TIMER; | ||
132 | PASS_RC(ata_wait_for_not_bsy(timeout), 2, 0); | ||
133 | while (true) | ||
134 | { | ||
135 | uint8_t dad = ata_read_cbr(&ATA_PIO_DAD); | ||
136 | if (dad & BIT(0)) RET_ERR(1); | ||
137 | if ((dad & (BIT(7) | BIT(3))) == BIT(3)) return 0; | ||
138 | if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(2); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | static int ata_wait_for_end_of_transfer(long timeout) | ||
143 | { | ||
144 | PASS_RC(ata_wait_for_not_bsy(timeout), 2, 0); | ||
145 | uint8_t dad = ata_read_cbr(&ATA_PIO_DAD); | ||
146 | if (dad & BIT(0)) RET_ERR(1); | ||
147 | if ((dad & (BIT(3) | BITRANGE(5, 7))) == BIT(6)) return 0; | ||
148 | RET_ERR(2); | ||
149 | } | ||
150 | |||
151 | int mmc_dsta_check_command_success(bool disable_crc) | ||
152 | { | ||
153 | int rc = 0; | ||
154 | uint32_t dsta = SDCI_DSTA; | ||
155 | if (dsta & SDCI_DSTA_RESTOUTE) rc |= 1; | ||
156 | if (dsta & SDCI_DSTA_RESENDE) rc |= 2; | ||
157 | if (dsta & SDCI_DSTA_RESINDE) rc |= 4; | ||
158 | if (!disable_crc) | ||
159 | if (dsta & SDCI_DSTA_RESCRCE) | ||
160 | rc |= 8; | ||
161 | if (rc) RET_ERR(rc); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | bool mmc_send_command(uint32_t cmd, uint32_t arg, uint32_t* result, int timeout) | ||
166 | { | ||
167 | long starttime = USEC_TIMER; | ||
168 | while ((SDCI_STATE & SDCI_STATE_CMD_STATE_MASK) != SDCI_STATE_CMD_STATE_CMD_IDLE) | ||
169 | { | ||
170 | if (TIMEOUT_EXPIRED(starttime, timeout)) RET_ERR(0); | ||
171 | yield(); | ||
172 | } | ||
173 | SDCI_STAC = SDCI_STAC_CLR_CMDEND | SDCI_STAC_CLR_BIT_3 | ||
174 | | SDCI_STAC_CLR_RESEND | SDCI_STAC_CLR_DATEND | ||
175 | | SDCI_STAC_CLR_DAT_CRCEND | SDCI_STAC_CLR_CRC_STAEND | ||
176 | | SDCI_STAC_CLR_RESTOUTE | SDCI_STAC_CLR_RESENDE | ||
177 | | SDCI_STAC_CLR_RESINDE | SDCI_STAC_CLR_RESCRCE | ||
178 | | SDCI_STAC_CLR_WR_DATCRCE | SDCI_STAC_CLR_RD_DATCRCE | ||
179 | | SDCI_STAC_CLR_RD_DATENDE0 | SDCI_STAC_CLR_RD_DATENDE1 | ||
180 | | SDCI_STAC_CLR_RD_DATENDE2 | SDCI_STAC_CLR_RD_DATENDE3 | ||
181 | | SDCI_STAC_CLR_RD_DATENDE4 | SDCI_STAC_CLR_RD_DATENDE5 | ||
182 | | SDCI_STAC_CLR_RD_DATENDE6 | SDCI_STAC_CLR_RD_DATENDE7; | ||
183 | SDCI_ARGU = arg; | ||
184 | SDCI_CMD = cmd; | ||
185 | if (!(SDCI_DSTA & SDCI_DSTA_CMDRDY)) RET_ERR(1); | ||
186 | SDCI_CMD = cmd | SDCI_CMD_CMDSTR; | ||
187 | long sleepbase = USEC_TIMER; | ||
188 | while (TIMEOUT_EXPIRED(sleepbase, 1000)) yield(); | ||
189 | while (!(SDCI_DSTA & SDCI_DSTA_CMDEND)) | ||
190 | { | ||
191 | if (TIMEOUT_EXPIRED(starttime, timeout)) RET_ERR(2); | ||
192 | yield(); | ||
193 | } | ||
194 | if ((cmd & SDCI_CMD_RES_TYPE_MASK) != SDCI_CMD_RES_TYPE_NONE) | ||
195 | { | ||
196 | while (!(SDCI_DSTA & SDCI_DSTA_RESEND)) | ||
197 | { | ||
198 | if (TIMEOUT_EXPIRED(starttime, timeout)) RET_ERR(3); | ||
199 | yield(); | ||
200 | } | ||
201 | if (cmd & SDCI_CMD_RES_BUSY) | ||
202 | while (SDCI_DSTA & SDCI_DSTA_DAT_BUSY) | ||
203 | { | ||
204 | if (TIMEOUT_EXPIRED(starttime, CEATA_DAT_NONBUSY_TIMEOUT)) RET_ERR(4); | ||
205 | yield(); | ||
206 | } | ||
207 | } | ||
208 | bool nocrc = (cmd & SDCI_CMD_RES_SIZE_MASK) == SDCI_CMD_RES_SIZE_136; | ||
209 | PASS_RC(mmc_dsta_check_command_success(nocrc), 3, 5); | ||
210 | if (result) *result = SDCI_RESP0; | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | int mmc_get_card_status(uint32_t* result) | ||
215 | { | ||
216 | return mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SEND_STATUS) | ||
217 | | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R1 | ||
218 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
219 | MMC_CMD_SEND_STATUS_RCA(CEATA_MMC_RCA), result, CEATA_COMMAND_TIMEOUT); | ||
220 | } | ||
221 | |||
222 | int mmc_init(void) | ||
223 | { | ||
224 | sleep(HZ / 10); | ||
225 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_GO_IDLE_STATE) | ||
226 | | SDCI_CMD_CMD_TYPE_BC | SDCI_CMD_RES_TYPE_NONE | ||
227 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NID, | ||
228 | 0, NULL, CEATA_COMMAND_TIMEOUT), 3, 0); | ||
229 | long startusec = USEC_TIMER; | ||
230 | uint32_t result; | ||
231 | do | ||
232 | { | ||
233 | if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT)) RET_ERR(1); | ||
234 | sleep(HZ / 100); | ||
235 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SEND_OP_COND) | ||
236 | | SDCI_CMD_CMD_TYPE_BCR | SDCI_CMD_RES_TYPE_R3 | ||
237 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NID, | ||
238 | MMC_CMD_SEND_OP_COND_OCR(MMC_OCR_270_360), | ||
239 | NULL, CEATA_COMMAND_TIMEOUT), 3, 2); | ||
240 | result = SDCI_RESP0; | ||
241 | } | ||
242 | while (!(result & MMC_OCR_POWER_UP_DONE)); | ||
243 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_ALL_SEND_CID) | ||
244 | | SDCI_CMD_CMD_TYPE_BCR | SDCI_CMD_RES_TYPE_R2 | ||
245 | | SDCI_CMD_RES_SIZE_136 | SDCI_CMD_NCR_NID_NID, | ||
246 | 0, NULL, CEATA_COMMAND_TIMEOUT), 3, 3); | ||
247 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SET_RELATIVE_ADDR) | ||
248 | | SDCI_CMD_CMD_TYPE_BCR | SDCI_CMD_RES_TYPE_R1 | ||
249 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
250 | MMC_CMD_SET_RELATIVE_ADDR_RCA(CEATA_MMC_RCA), | ||
251 | NULL, CEATA_COMMAND_TIMEOUT), 3, 4); | ||
252 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SELECT_CARD) | ||
253 | | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R1 | ||
254 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
255 | MMC_CMD_SELECT_CARD_RCA(CEATA_MMC_RCA), | ||
256 | NULL, CEATA_COMMAND_TIMEOUT), 3, 5); | ||
257 | PASS_RC(mmc_get_card_status(&result), 3, 6); | ||
258 | if ((result & MMC_STATUS_CURRENT_STATE_MASK) != MMC_STATUS_CURRENT_STATE_TRAN) RET_ERR(7); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | int mmc_fastio_write(uint32_t addr, uint32_t data) | ||
263 | { | ||
264 | return mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_FAST_IO) | ||
265 | | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R4 | ||
266 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
267 | MMC_CMD_FAST_IO_RCA(CEATA_MMC_RCA) | MMC_CMD_FAST_IO_DIRECTION_WRITE | ||
268 | | MMC_CMD_FAST_IO_ADDRESS(addr) | MMC_CMD_FAST_IO_DATA(data), | ||
269 | NULL, CEATA_COMMAND_TIMEOUT); | ||
270 | } | ||
271 | |||
272 | int mmc_fastio_read(uint32_t addr, uint32_t* data) | ||
273 | { | ||
274 | return mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_FAST_IO) | ||
275 | | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R4 | ||
276 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
277 | MMC_CMD_FAST_IO_RCA(CEATA_MMC_RCA) | MMC_CMD_FAST_IO_DIRECTION_READ | ||
278 | | MMC_CMD_FAST_IO_ADDRESS(addr), data, CEATA_COMMAND_TIMEOUT); | ||
279 | } | ||
280 | |||
281 | int ceata_soft_reset(void) | ||
282 | { | ||
283 | PASS_RC(mmc_fastio_write(6, 4), 2, 0); | ||
284 | sleep(HZ / 100); | ||
285 | PASS_RC(mmc_fastio_write(6, 0), 2, 1); | ||
286 | sleep(HZ / 100); | ||
287 | long startusec = USEC_TIMER; | ||
288 | uint32_t status; | ||
289 | do | ||
290 | { | ||
291 | PASS_RC(mmc_fastio_read(0xf, &status), 2, 2); | ||
292 | if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT)) RET_ERR(3); | ||
293 | sleep(HZ / 100); | ||
294 | } | ||
295 | while (status & 0x80); | ||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | int mmc_dsta_check_data_success(void) | ||
300 | { | ||
301 | int rc = 0; | ||
302 | uint32_t dsta = SDCI_DSTA; | ||
303 | if (dsta & (SDCI_DSTA_WR_DATCRCE | SDCI_DSTA_RD_DATCRCE)) | ||
304 | { | ||
305 | if (dsta & SDCI_DSTA_WR_DATCRCE) rc |= 1; | ||
306 | if (dsta & SDCI_DSTA_RD_DATCRCE) rc |= 2; | ||
307 | if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_TXERR) rc |= 4; | ||
308 | else if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_CARDERR) rc |= 8; | ||
309 | } | ||
310 | if (dsta & (SDCI_DSTA_RD_DATENDE0 | SDCI_DSTA_RD_DATENDE1 | SDCI_DSTA_RD_DATENDE2 | ||
311 | | SDCI_DSTA_RD_DATENDE3 | SDCI_DSTA_RD_DATENDE4 | SDCI_DSTA_RD_DATENDE5 | ||
312 | | SDCI_DSTA_RD_DATENDE6 | SDCI_DSTA_RD_DATENDE7)) | ||
313 | rc |= 16; | ||
314 | if (rc) RET_ERR(rc); | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | void mmc_discard_irq(void) | ||
319 | { | ||
320 | SDCI_IRQ = SDCI_IRQ_DAT_DONE_INT | SDCI_IRQ_MASK_MASK_IOCARD_IRQ_INT | ||
321 | | SDCI_IRQ_MASK_MASK_READ_WAIT_INT; | ||
322 | wakeup_wait(&mmc_wakeup, 0); | ||
323 | } | ||
324 | |||
325 | int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size) | ||
326 | { | ||
327 | if (size > 0x10) RET_ERR(0); | ||
328 | mmc_discard_irq(); | ||
329 | SDCI_DMASIZE = size; | ||
330 | SDCI_DMACOUNT = 1; | ||
331 | SDCI_DMAADDR = dest; | ||
332 | SDCI_DCTRL = SDCI_DCTRL_TXFIFORST | SDCI_DCTRL_RXFIFORST; | ||
333 | invalidate_dcache(); | ||
334 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_CEATA_RW_MULTIPLE_REG) | ||
335 | | SDCI_CMD_CMD_TYPE_ADTC | SDCI_CMD_RES_TYPE_R1 | ||
336 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
337 | MMC_CMD_CEATA_RW_MULTIPLE_REG_DIRECTION_READ | ||
338 | | MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS(addr & 0xfc) | ||
339 | | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc), | ||
340 | NULL, CEATA_COMMAND_TIMEOUT), 2, 1); | ||
341 | if (wakeup_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) == OBJ_WAIT_TIMEDOUT) RET_ERR(2); | ||
342 | PASS_RC(mmc_dsta_check_data_success(), 2, 3); | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | int ceata_write_multiple_register(uint32_t addr, void* dest, uint32_t size) | ||
347 | { | ||
348 | uint32_t i; | ||
349 | if (size > 0x10) RET_ERR(0); | ||
350 | mmc_discard_irq(); | ||
351 | SDCI_DMASIZE = size; | ||
352 | SDCI_DMACOUNT = 0; | ||
353 | SDCI_DCTRL = SDCI_DCTRL_TXFIFORST | SDCI_DCTRL_RXFIFORST; | ||
354 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_CEATA_RW_MULTIPLE_REG) | ||
355 | | SDCI_CMD_CMD_TYPE_ADTC | SDCI_CMD_CMD_RD_WR | ||
356 | | SDCI_CMD_RES_BUSY | SDCI_CMD_RES_TYPE_R1 | ||
357 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
358 | MMC_CMD_CEATA_RW_MULTIPLE_REG_DIRECTION_WRITE | ||
359 | | MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS(addr & 0xfc) | ||
360 | | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc), | ||
361 | NULL, CEATA_COMMAND_TIMEOUT), 3, 1); | ||
362 | SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX; | ||
363 | for (i = 0; i < size / 4; i++) SDCI_DATA = ((uint32_t*)dest)[i]; | ||
364 | long startusec = USEC_TIMER; | ||
365 | if (wakeup_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) == OBJ_WAIT_TIMEDOUT) RET_ERR(2); | ||
366 | while ((SDCI_STATE & SDCI_STATE_DAT_STATE_MASK) != SDCI_STATE_DAT_STATE_IDLE) | ||
367 | { | ||
368 | if (TIMEOUT_EXPIRED(startusec, CEATA_COMMAND_TIMEOUT)) RET_ERR(3); | ||
369 | yield(); | ||
370 | } | ||
371 | PASS_RC(mmc_dsta_check_data_success(), 3, 4); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | int ceata_init(int buswidth) | ||
376 | { | ||
377 | uint32_t result; | ||
378 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SWITCH) | SDCI_CMD_RES_BUSY | ||
379 | | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R1 | ||
380 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
381 | MMC_CMD_SWITCH_ACCESS_WRITE_BYTE | ||
382 | | MMC_CMD_SWITCH_INDEX(MMC_CMD_SWITCH_FIELD_HS_TIMING) | ||
383 | | MMC_CMD_SWITCH_VALUE(MMC_CMD_SWITCH_FIELD_HS_TIMING_HIGH_SPEED), | ||
384 | &result, CEATA_COMMAND_TIMEOUT), 3, 0); | ||
385 | if (result & MMC_STATUS_SWITCH_ERROR) RET_ERR(1); | ||
386 | if (buswidth > 1) | ||
387 | { | ||
388 | int setting; | ||
389 | if (buswidth == 4) setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_4BIT; | ||
390 | else if (buswidth == 8) setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_8BIT; | ||
391 | else setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_1BIT; | ||
392 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SWITCH) | SDCI_CMD_RES_BUSY | ||
393 | | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R1 | ||
394 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
395 | MMC_CMD_SWITCH_ACCESS_WRITE_BYTE | ||
396 | | MMC_CMD_SWITCH_INDEX(MMC_CMD_SWITCH_FIELD_BUS_WIDTH) | ||
397 | | MMC_CMD_SWITCH_VALUE(setting), | ||
398 | &result, CEATA_COMMAND_TIMEOUT), 3, 2); | ||
399 | if (result & MMC_STATUS_SWITCH_ERROR) RET_ERR(3); | ||
400 | if (buswidth == 4) | ||
401 | SDCI_CTRL = (SDCI_CTRL & ~SDCI_CTRL_BUS_WIDTH_MASK) | SDCI_CTRL_BUS_WIDTH_4BIT; | ||
402 | else if (buswidth == 8) | ||
403 | SDCI_CTRL = (SDCI_CTRL & ~SDCI_CTRL_BUS_WIDTH_MASK) | SDCI_CTRL_BUS_WIDTH_8BIT; | ||
404 | } | ||
405 | PASS_RC(ceata_soft_reset(), 3, 4); | ||
406 | PASS_RC(ceata_read_multiple_register(0, ceata_taskfile, 0x10), 3, 5); | ||
407 | if (ceata_taskfile[0xc] != 0xce || ceata_taskfile[0xd] != 0xaa) RET_ERR(6); | ||
408 | PASS_RC(mmc_fastio_write(6, 0), 3, 7); | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | int ceata_check_error(void) | ||
413 | { | ||
414 | uint32_t status, error; | ||
415 | PASS_RC(mmc_fastio_read(0xf, &status), 2, 0); | ||
416 | if (status & 1) | ||
417 | { | ||
418 | PASS_RC(mmc_fastio_read(0x9, &error), 2, 1); | ||
419 | RET_ERR((error << 2) | 2); | ||
420 | } | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | int ceata_wait_idle(void) | ||
425 | { | ||
426 | long startusec = USEC_TIMER; | ||
427 | while (true) | ||
428 | { | ||
429 | uint32_t status; | ||
430 | PASS_RC(mmc_fastio_read(0xf, &status), 1, 0); | ||
431 | if (!(status & 0x88)) return 0; | ||
432 | if (TIMEOUT_EXPIRED(startusec, CEATA_DAT_NONBUSY_TIMEOUT)) RET_ERR(1); | ||
433 | sleep(HZ / 20); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | int ceata_cancel_command(void) | ||
438 | { | ||
439 | *((uint32_t volatile*)0x3cf00200) = 0x9000e; | ||
440 | udelay(1); | ||
441 | *((uint32_t volatile*)0x3cf00200) = 0x9000f; | ||
442 | udelay(1); | ||
443 | *((uint32_t volatile*)0x3cf00200) = 0x90003; | ||
444 | udelay(1); | ||
445 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_STOP_TRANSMISSION) | ||
446 | | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R1 | SDCI_CMD_RES_BUSY | ||
447 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
448 | 0, NULL, CEATA_COMMAND_TIMEOUT), 1, 0); | ||
449 | PASS_RC(ceata_wait_idle(), 1, 1); | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | int ceata_rw_multiple_block(bool write, void* buf, uint32_t count, long timeout) | ||
454 | { | ||
455 | mmc_discard_irq(); | ||
456 | uint32_t responsetype; | ||
457 | uint32_t cmdtype; | ||
458 | uint32_t direction; | ||
459 | if (write) | ||
460 | { | ||
461 | cmdtype = SDCI_CMD_CMD_TYPE_ADTC | SDCI_CMD_CMD_RD_WR; | ||
462 | responsetype = SDCI_CMD_RES_TYPE_R1 | SDCI_CMD_RES_BUSY; | ||
463 | direction = MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_DIRECTION_WRITE; | ||
464 | } | ||
465 | else | ||
466 | { | ||
467 | cmdtype = SDCI_CMD_CMD_TYPE_ADTC; | ||
468 | responsetype = SDCI_CMD_RES_TYPE_R1; | ||
469 | direction = MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_DIRECTION_READ; | ||
470 | } | ||
471 | SDCI_DMASIZE = 0x200; | ||
472 | SDCI_DMAADDR = buf; | ||
473 | SDCI_DMACOUNT = count; | ||
474 | SDCI_DCTRL = SDCI_DCTRL_TXFIFORST | SDCI_DCTRL_RXFIFORST; | ||
475 | invalidate_dcache(); | ||
476 | PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_CEATA_RW_MULTIPLE_BLOCK) | ||
477 | | SDCI_CMD_CMD_TYPE_ADTC | cmdtype | responsetype | ||
478 | | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, | ||
479 | direction | MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT(count), | ||
480 | NULL, CEATA_COMMAND_TIMEOUT), 4, 0); | ||
481 | if (write) SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX; | ||
482 | if (wakeup_wait(&mmc_wakeup, timeout) == OBJ_WAIT_TIMEDOUT) | ||
483 | { | ||
484 | PASS_RC(ceata_cancel_command(), 4, 1); | ||
485 | RET_ERR(2); | ||
486 | } | ||
487 | PASS_RC(mmc_dsta_check_data_success(), 4, 3); | ||
488 | if (wakeup_wait(&mmc_comp_wakeup, timeout) == OBJ_WAIT_TIMEDOUT) | ||
489 | { | ||
490 | PASS_RC(ceata_cancel_command(), 4, 4); | ||
491 | RET_ERR(4); | ||
492 | } | ||
493 | PASS_RC(ceata_check_error(), 4, 5); | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | int ata_identify(uint16_t* buf) | ||
498 | { | ||
499 | int i; | ||
500 | if (ceata) | ||
501 | { | ||
502 | memset(ceata_taskfile, 0, 16); | ||
503 | ceata_taskfile[0xf] = 0xec; | ||
504 | PASS_RC(ceata_wait_idle(), 2, 0); | ||
505 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1); | ||
506 | PASS_RC(ceata_rw_multiple_block(false, buf, 1, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 2, 2); | ||
507 | } | ||
508 | else | ||
509 | { | ||
510 | PASS_RC(ata_wait_for_not_bsy(10000000), 1, 0); | ||
511 | ata_write_cbr(&ATA_PIO_DVR, 0); | ||
512 | ata_write_cbr(&ATA_PIO_CSD, 0xec); | ||
513 | PASS_RC(ata_wait_for_start_of_transfer(10000000), 1, 1); | ||
514 | for (i = 0; i < 0x100; i++) | ||
515 | { | ||
516 | uint16_t word = ata_read_cbr(&ATA_PIO_DTR); | ||
517 | buf[i] = (word >> 8) | (word << 8); | ||
518 | } | ||
519 | } | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | void ata_set_active(void) | ||
524 | { | ||
525 | ata_last_activity_value = current_tick; | ||
526 | } | ||
527 | |||
528 | bool ata_disk_is_active(void) | ||
529 | { | ||
530 | return ata_powered; | ||
531 | } | ||
532 | |||
533 | int ata_set_feature(uint32_t feature, uint32_t param) | ||
534 | { | ||
535 | PASS_RC(ata_wait_for_rdy(500000), 1, 0); | ||
536 | ata_write_cbr(&ATA_PIO_DVR, 0); | ||
537 | ata_write_cbr(&ATA_PIO_FED, 3); | ||
538 | ata_write_cbr(&ATA_PIO_SCR, param); | ||
539 | ata_write_cbr(&ATA_PIO_CSD, feature); | ||
540 | PASS_RC(ata_wait_for_rdy(500000), 1, 1); | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | int ata_power_up(void) | ||
545 | { | ||
546 | ata_set_active(); | ||
547 | if (ata_powered) return 0; | ||
548 | ide_power_enable(true); | ||
549 | long spinup_start = current_tick; | ||
550 | if (ceata) | ||
551 | { | ||
552 | PWRCON(0) &= ~(1 << 9); | ||
553 | SDCI_RESET = 0xa5; | ||
554 | sleep(HZ / 100); | ||
555 | *((uint32_t volatile*)0x3cf00380) = 0; | ||
556 | *((uint32_t volatile*)0x3cf0010c) = 0xff; | ||
557 | SDCI_CTRL = SDCI_CTRL_SDCIEN | SDCI_CTRL_CLK_SEL_SDCLK | ||
558 | | SDCI_CTRL_BIT_8 | SDCI_CTRL_BIT_14; | ||
559 | SDCI_CDIV = SDCI_CDIV_CLKDIV(260); | ||
560 | *((uint32_t volatile*)0x3cf00200) = 0xb000f; | ||
561 | SDCI_IRQ_MASK = SDCI_IRQ_MASK_MASK_DAT_DONE_INT | SDCI_IRQ_MASK_MASK_IOCARD_IRQ_INT; | ||
562 | PASS_RC(mmc_init(), 2, 0); | ||
563 | SDCI_CDIV = SDCI_CDIV_CLKDIV(4); | ||
564 | sleep(HZ / 100); | ||
565 | PASS_RC(ceata_init(8), 2, 1); | ||
566 | PASS_RC(ata_identify(ata_identify_data), 2, 2); | ||
567 | dma_mode = 0x44; | ||
568 | } | ||
569 | else | ||
570 | { | ||
571 | PWRCON(0) &= ~(1 << 5); | ||
572 | ATA_CFG = BIT(0); | ||
573 | sleep(HZ / 100); | ||
574 | ATA_CFG = 0; | ||
575 | sleep(HZ / 100); | ||
576 | ATA_SWRST = BIT(0); | ||
577 | sleep(HZ / 100); | ||
578 | ATA_SWRST = 0; | ||
579 | sleep(HZ / 10); | ||
580 | ATA_CONTROL = BIT(0); | ||
581 | sleep(HZ / 5); | ||
582 | ATA_PIO_TIME = 0x191f7; | ||
583 | ATA_PIO_LHR = 0; | ||
584 | while (!(ATA_PIO_READY & BIT(1))) yield(); | ||
585 | PASS_RC(ata_identify(ata_identify_data), 2, 0); | ||
586 | uint32_t piotime = 0x11f3; | ||
587 | uint32_t mdmatime = 0x1c175; | ||
588 | uint32_t udmatime = 0x5071152; | ||
589 | uint32_t param = 0; | ||
590 | ata_dma_flags = 0; | ||
591 | ata_lba48 = ata_identify_data[83] & BIT(10) ? true : false; | ||
592 | if (ata_identify_data[53] & BIT(1)) | ||
593 | { | ||
594 | if (ata_identify_data[64] & BIT(1)) piotime = 0x2072; | ||
595 | else if (ata_identify_data[64] & BIT(0)) piotime = 0x7083; | ||
596 | } | ||
597 | if (ata_identify_data[63] & BIT(2)) | ||
598 | { | ||
599 | mdmatime = 0x5072; | ||
600 | param = 0x22; | ||
601 | } | ||
602 | else if (ata_identify_data[63] & BIT(1)) | ||
603 | { | ||
604 | mdmatime = 0x7083; | ||
605 | param = 0x21; | ||
606 | } | ||
607 | if (ata_identify_data[63] & BITRANGE(0, 2)) | ||
608 | { | ||
609 | ata_dma_flags = BIT(3) | BIT(10); | ||
610 | param |= 0x20; | ||
611 | } | ||
612 | if (ata_identify_data[53] & BIT(2)) | ||
613 | { | ||
614 | if (ata_identify_data[88] & BIT(4)) | ||
615 | { | ||
616 | udmatime = 0x2010a52; | ||
617 | param = 0x44; | ||
618 | } | ||
619 | else if (ata_identify_data[88] & BIT(3)) | ||
620 | { | ||
621 | udmatime = 0x2020a52; | ||
622 | param = 0x43; | ||
623 | } | ||
624 | else if (ata_identify_data[88] & BIT(2)) | ||
625 | { | ||
626 | udmatime = 0x3030a52; | ||
627 | param = 0x42; | ||
628 | } | ||
629 | else if (ata_identify_data[88] & BIT(1)) | ||
630 | { | ||
631 | udmatime = 0x3050a52; | ||
632 | param = 0x41; | ||
633 | } | ||
634 | if (ata_identify_data[88] & BITRANGE(0, 4)) | ||
635 | { | ||
636 | ata_dma_flags = BIT(2) | BIT(3) | BIT(9) | BIT(10); | ||
637 | param |= 0x40; | ||
638 | } | ||
639 | } | ||
640 | ata_dma = param ? true : false; | ||
641 | dma_mode = param; | ||
642 | PASS_RC(ata_set_feature(0xef, param), 2, 1); | ||
643 | if (ata_identify_data[82] & BIT(5)) PASS_RC(ata_set_feature(0x02, 0), 2, 2); | ||
644 | if (ata_identify_data[82] & BIT(6)) PASS_RC(ata_set_feature(0x55, 0), 2, 3); | ||
645 | ATA_PIO_TIME = piotime; | ||
646 | ATA_MDMA_TIME = mdmatime; | ||
647 | ATA_UDMA_TIME = udmatime; | ||
648 | } | ||
649 | spinup_time = current_tick - spinup_start; | ||
650 | if (ata_lba48) | ||
651 | ata_total_sectors = ata_identify_data[100] | ||
652 | | (((uint64_t)ata_identify_data[101]) << 16) | ||
653 | | (((uint64_t)ata_identify_data[102]) << 32) | ||
654 | | (((uint64_t)ata_identify_data[103]) << 48); | ||
655 | else ata_total_sectors = ata_identify_data[60] | (((uint32_t)ata_identify_data[61]) << 16); | ||
656 | ata_total_sectors >>= 3; | ||
657 | ata_powered = true; | ||
658 | ata_set_active(); | ||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | void ata_power_down(void) | ||
663 | { | ||
664 | if (!ata_powered) return; | ||
665 | ata_powered = false; | ||
666 | if (ceata) | ||
667 | { | ||
668 | memset(ceata_taskfile, 0, 16); | ||
669 | ceata_taskfile[0xf] = 0xe0; | ||
670 | ceata_wait_idle(); | ||
671 | ceata_write_multiple_register(0, ceata_taskfile, 16); | ||
672 | sleep(HZ); | ||
673 | PWRCON(0) |= (1 << 9); | ||
674 | } | ||
675 | else | ||
676 | { | ||
677 | ata_wait_for_rdy(1000000); | ||
678 | ata_write_cbr(&ATA_PIO_DVR, 0); | ||
679 | ata_write_cbr(&ATA_PIO_CSD, 0xe0); | ||
680 | ata_wait_for_rdy(1000000); | ||
681 | sleep(HZ / 30); | ||
682 | ATA_CONTROL = 0; | ||
683 | while (!(ATA_CONTROL & BIT(1))) yield(); | ||
684 | PWRCON(0) |= (1 << 5); | ||
685 | } | ||
686 | ide_power_enable(false); | ||
687 | } | ||
688 | |||
689 | int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bool write) | ||
690 | { | ||
691 | if (ceata) | ||
692 | { | ||
693 | memset(ceata_taskfile, 0, 16); | ||
694 | ceata_taskfile[0x2] = cnt >> 5; | ||
695 | ceata_taskfile[0x3] = sector >> 21; | ||
696 | ceata_taskfile[0x4] = sector >> 29; | ||
697 | ceata_taskfile[0x5] = sector >> 37; | ||
698 | ceata_taskfile[0xa] = cnt << 3; | ||
699 | ceata_taskfile[0xb] = sector << 3; | ||
700 | ceata_taskfile[0xc] = sector >> 5; | ||
701 | ceata_taskfile[0xd] = sector >> 13; | ||
702 | ceata_taskfile[0xf] = write ? 0x35 : 0x25; | ||
703 | PASS_RC(ceata_wait_idle(), 2, 0); | ||
704 | PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1); | ||
705 | PASS_RC(ceata_rw_multiple_block(write, buffer, cnt << 3, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 2, 2); | ||
706 | } | ||
707 | else | ||
708 | { | ||
709 | PASS_RC(ata_wait_for_rdy(100000), 2, 0); | ||
710 | ata_write_cbr(&ATA_PIO_DVR, 0); | ||
711 | if (ata_lba48) | ||
712 | { | ||
713 | ata_write_cbr(&ATA_PIO_SCR, cnt >> 5); | ||
714 | ata_write_cbr(&ATA_PIO_SCR, (cnt << 3) & 0xff); | ||
715 | ata_write_cbr(&ATA_PIO_LHR, (sector >> 37) & 0xff); | ||
716 | ata_write_cbr(&ATA_PIO_LMR, (sector >> 29) & 0xff); | ||
717 | ata_write_cbr(&ATA_PIO_LLR, (sector >> 21) & 0xff); | ||
718 | ata_write_cbr(&ATA_PIO_LHR, (sector >> 13) & 0xff); | ||
719 | ata_write_cbr(&ATA_PIO_LMR, (sector >> 5) & 0xff); | ||
720 | ata_write_cbr(&ATA_PIO_LLR, (sector << 3) & 0xff); | ||
721 | ata_write_cbr(&ATA_PIO_DVR, BIT(6)); | ||
722 | if (write) ata_write_cbr(&ATA_PIO_CSD, ata_dma ? 0x35 : 0x39); | ||
723 | else ata_write_cbr(&ATA_PIO_CSD, ata_dma ? 0x25 : 0x29); | ||
724 | } | ||
725 | else | ||
726 | { | ||
727 | ata_write_cbr(&ATA_PIO_SCR, (cnt << 3) & 0xff); | ||
728 | ata_write_cbr(&ATA_PIO_LHR, (sector >> 13) & 0xff); | ||
729 | ata_write_cbr(&ATA_PIO_LMR, (sector >> 5) & 0xff); | ||
730 | ata_write_cbr(&ATA_PIO_LLR, (sector << 3) & 0xff); | ||
731 | ata_write_cbr(&ATA_PIO_DVR, BIT(6) | ((sector >> 21) & 0xf)); | ||
732 | if (write) ata_write_cbr(&ATA_PIO_CSD, ata_dma ? 0xca : 0x30); | ||
733 | else ata_write_cbr(&ATA_PIO_CSD, ata_dma ? 0xc8 : 0xc4); | ||
734 | } | ||
735 | if (ata_dma) | ||
736 | { | ||
737 | PASS_RC(ata_wait_for_start_of_transfer(500000), 2, 1); | ||
738 | if (write) | ||
739 | { | ||
740 | ATA_SBUF_START = buffer; | ||
741 | ATA_SBUF_SIZE = SECTOR_SIZE * cnt; | ||
742 | ATA_CFG |= BIT(4); | ||
743 | } | ||
744 | else | ||
745 | { | ||
746 | ATA_TBUF_START = buffer; | ||
747 | ATA_TBUF_SIZE = SECTOR_SIZE * cnt; | ||
748 | ATA_CFG &= ~BIT(4); | ||
749 | } | ||
750 | ATA_XFR_NUM = SECTOR_SIZE * cnt - 1; | ||
751 | ATA_CFG |= ata_dma_flags; | ||
752 | ATA_CFG &= ~(BIT(7) | BIT(8)); | ||
753 | wakeup_wait(&ata_wakeup, 0); | ||
754 | ATA_IRQ = BITRANGE(0, 4); | ||
755 | ATA_IRQ_MASK = BIT(0); | ||
756 | ATA_COMMAND = BIT(0); | ||
757 | if (wakeup_wait(&ata_wakeup, 500000 * HZ / 1000000) == OBJ_WAIT_TIMEDOUT) | ||
758 | { | ||
759 | ATA_COMMAND = BIT(1); | ||
760 | ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12)); | ||
761 | RET_ERR(2); | ||
762 | } | ||
763 | ATA_COMMAND = BIT(1); | ||
764 | ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12)); | ||
765 | } | ||
766 | else | ||
767 | { | ||
768 | cnt *= SECTOR_SIZE / 512; | ||
769 | while (cnt--) | ||
770 | { | ||
771 | int i; | ||
772 | PASS_RC(ata_wait_for_start_of_transfer(500000), 2, 1); | ||
773 | if (write) | ||
774 | for (i = 0; i < 256; i++) | ||
775 | ata_write_cbr(&ATA_PIO_DTR, ((uint16_t*)buffer)[i]); | ||
776 | else | ||
777 | for (i = 0; i < 256; i++) | ||
778 | ((uint16_t*)buffer)[i] = ata_read_cbr(&ATA_PIO_DTR); | ||
779 | buffer += 512; | ||
780 | } | ||
781 | } | ||
782 | PASS_RC(ata_wait_for_end_of_transfer(100000), 2, 3); | ||
783 | } | ||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | int ata_rw_chunk(uint64_t sector, uint32_t cnt, void* buffer, bool write) | ||
788 | { | ||
789 | led(true); | ||
790 | int rc = ata_rw_chunk_internal(sector, cnt, buffer, write); | ||
791 | led(false); | ||
792 | return rc; | ||
793 | } | ||
794 | |||
795 | #ifdef ATA_HAVE_BBT | ||
796 | int ata_bbt_translate(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount) | ||
797 | { | ||
798 | if (sector + count > ata_virtual_sectors) RET_ERR(0); | ||
799 | if (!ata_bbt) | ||
800 | { | ||
801 | *phys = sector; | ||
802 | *physcount = count; | ||
803 | return 0; | ||
804 | } | ||
805 | if (!count) | ||
806 | { | ||
807 | *phys = 0; | ||
808 | *physcount = 0; | ||
809 | return 0; | ||
810 | } | ||
811 | uint32_t offset; | ||
812 | uint32_t l0idx = sector >> 15; | ||
813 | uint32_t l0offs = sector & 0x7fff; | ||
814 | *physcount = MIN(count, 0x8000 - l0offs); | ||
815 | uint32_t l0data = ata_bbt[0][l0idx << 1]; | ||
816 | uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12; | ||
817 | if (l0data < 0x8000) offset = l0data + base; | ||
818 | else | ||
819 | { | ||
820 | uint32_t l1idx = (sector >> 10) & 0x1f; | ||
821 | uint32_t l1offs = sector & 0x3ff; | ||
822 | *physcount = MIN(count, 0x400 - l1offs); | ||
823 | uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx]; | ||
824 | if (l1data < 0x8000) offset = l1data + base; | ||
825 | else | ||
826 | { | ||
827 | uint32_t l2idx = (sector >> 5) & 0x1f; | ||
828 | uint32_t l2offs = sector & 0x1f; | ||
829 | *physcount = MIN(count, 0x20 - l2offs); | ||
830 | uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx]; | ||
831 | if (l2data < 0x8000) offset = l2data + base; | ||
832 | else | ||
833 | { | ||
834 | uint32_t l3idx = sector & 0x1f; | ||
835 | uint32_t l3data = ata_bbt[l2data & 0x7fff][l3idx]; | ||
836 | for (*physcount = 1; *physcount < count && l3idx + *physcount < 0x20; *physcount++) | ||
837 | if (ata_bbt[l2data & 0x7fff][l3idx + *physcount] != l3data) | ||
838 | break; | ||
839 | offset = l3data + base; | ||
840 | } | ||
841 | } | ||
842 | } | ||
843 | *phys = sector + offset; | ||
844 | return 0; | ||
845 | } | ||
846 | #endif | ||
847 | |||
848 | int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write) | ||
849 | { | ||
850 | if (((uint32_t)buffer) & 0xf) | ||
851 | panicf("ATA: Misaligned data buffer at %08X (sector %lu, count %lu)", | ||
852 | (unsigned int)buffer, (long unsigned int)sector, (long unsigned int)count); | ||
853 | #ifdef ATA_HAVE_BBT | ||
854 | if (sector + count > ata_virtual_sectors) RET_ERR(0); | ||
855 | if (ata_bbt) | ||
856 | while (count) | ||
857 | { | ||
858 | uint64_t phys; | ||
859 | uint32_t cnt; | ||
860 | PASS_RC(ata_bbt_translate(sector, count, &phys, &cnt), 0, 0); | ||
861 | uint32_t offset = phys - sector; | ||
862 | if (offset != ata_last_offset && phys - ata_last_phys < 64) ata_soft_reset(); | ||
863 | ata_last_offset = offset; | ||
864 | ata_last_phys = phys + cnt; | ||
865 | PASS_RC(ata_rw_sectors_internal(phys, cnt, buffer, write), 0, 0); | ||
866 | buffer += cnt * SECTOR_SIZE; | ||
867 | sector += cnt; | ||
868 | count -= cnt; | ||
869 | } | ||
870 | else PASS_RC(ata_rw_sectors_internal(sector, count, buffer, write), 0, 0); | ||
871 | return 0; | ||
872 | } | ||
873 | |||
874 | int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool write) | ||
875 | { | ||
876 | #endif | ||
877 | if (sector + count > ata_total_sectors) RET_ERR(0); | ||
878 | if (!ata_powered) ata_power_up(); | ||
879 | ata_set_active(); | ||
880 | if (ata_dma && write) clean_dcache(); | ||
881 | else if (ata_dma) invalidate_dcache(); | ||
882 | if (!ceata) ATA_COMMAND = BIT(1); | ||
883 | while (count) | ||
884 | { | ||
885 | uint32_t cnt = MIN(ata_lba48 ? 8192 : 32, count); | ||
886 | int rc = -1; | ||
887 | rc = ata_rw_chunk(sector, cnt, buffer, write); | ||
888 | if (rc && ata_error_srst) ata_soft_reset(); | ||
889 | if (rc && ata_retries) | ||
890 | { | ||
891 | void* buf = buffer; | ||
892 | uint64_t sect; | ||
893 | for (sect = sector; sect < sector + cnt; sect++) | ||
894 | { | ||
895 | rc = -1; | ||
896 | int tries = ata_retries; | ||
897 | while (tries-- && rc) | ||
898 | { | ||
899 | rc = ata_rw_chunk(sect, 1, buf, write); | ||
900 | if (rc && ata_error_srst) ata_soft_reset(); | ||
901 | } | ||
902 | if (rc) break; | ||
903 | buf += SECTOR_SIZE; | ||
904 | } | ||
905 | } | ||
906 | PASS_RC(rc, 1, 1); | ||
907 | buffer += SECTOR_SIZE * cnt; | ||
908 | sector += cnt; | ||
909 | count -= cnt; | ||
910 | } | ||
911 | ata_set_active(); | ||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | static void ata_thread(void) | ||
916 | { | ||
917 | while (true) | ||
918 | { | ||
919 | mutex_lock(&ata_mutex); | ||
920 | if (TIME_AFTER(current_tick, ata_last_activity_value + ata_sleep_timeout) && ata_powered) | ||
921 | { | ||
922 | call_storage_idle_notifys(false); | ||
923 | ata_power_down(); | ||
924 | } | ||
925 | mutex_unlock(&ata_mutex); | ||
926 | sleep(HZ / 2); | ||
927 | } | ||
928 | } | ||
929 | |||
930 | /* API Functions */ | ||
931 | int ata_soft_reset(void) | ||
932 | { | ||
933 | int rc; | ||
934 | mutex_lock(&ata_mutex); | ||
935 | if (!ata_powered) ata_power_up(); | ||
936 | ata_set_active(); | ||
937 | if (ceata) rc = ceata_soft_reset(); | ||
938 | else | ||
939 | { | ||
940 | ata_write_cbr(&ATA_PIO_DAD, BIT(1) | BIT(2)); | ||
941 | udelay(10); | ||
942 | ata_write_cbr(&ATA_PIO_DAD, 0); | ||
943 | rc = ata_wait_for_rdy(20000000); | ||
944 | } | ||
945 | if (IS_ERR(rc)) | ||
946 | { | ||
947 | ata_power_down(); | ||
948 | sleep(HZ * 3); | ||
949 | ata_power_up(); | ||
950 | } | ||
951 | ata_set_active(); | ||
952 | mutex_unlock(&ata_mutex); | ||
953 | return rc; | ||
954 | } | ||
955 | |||
956 | int ata_read_sectors(IF_MD2(int drive,) unsigned long start, int incount, | ||
957 | void* inbuf) | ||
958 | { | ||
959 | mutex_lock(&ata_mutex); | ||
960 | int rc = ata_rw_sectors(start, incount, inbuf, false); | ||
961 | mutex_unlock(&ata_mutex); | ||
962 | return rc; | ||
963 | } | ||
964 | |||
965 | int ata_write_sectors(IF_MD2(int drive,) unsigned long start, int count, | ||
966 | const void* outbuf) | ||
967 | { | ||
968 | mutex_lock(&ata_mutex); | ||
969 | int rc = ata_rw_sectors(start, count, (void*)((uint32_t)outbuf), true); | ||
970 | mutex_unlock(&ata_mutex); | ||
971 | return rc; | ||
972 | } | ||
973 | |||
974 | void ata_spindown(int seconds) | ||
975 | { | ||
976 | ata_sleep_timeout = seconds * HZ; | ||
977 | } | ||
978 | |||
979 | void ata_sleep(void) | ||
980 | { | ||
981 | ata_last_activity_value = current_tick - ata_sleep_timeout + HZ / 5; | ||
982 | } | ||
983 | |||
984 | void ata_sleepnow(void) | ||
985 | { | ||
986 | mutex_lock(&ata_mutex); | ||
987 | ata_power_down(); | ||
988 | mutex_unlock(&ata_mutex); | ||
989 | } | ||
990 | |||
991 | void ata_close(void) | ||
992 | { | ||
993 | ata_sleepnow(); | ||
994 | } | ||
995 | |||
996 | void ata_spin(void) | ||
997 | { | ||
998 | ata_set_active(); | ||
999 | } | ||
1000 | |||
1001 | void ata_get_info(IF_MD2(int drive,) struct storage_info *info) | ||
1002 | { | ||
1003 | (*info).sector_size = SECTOR_SIZE; | ||
1004 | #ifdef ATA_HAVE_BBT | ||
1005 | (*info).num_sectors = ata_virtual_sectors; | ||
1006 | #else | ||
1007 | (*info).num_sectors = ata_total_sectors; | ||
1008 | #endif | ||
1009 | (*info).vendor = "Apple"; | ||
1010 | (*info).product = "iPod Classic"; | ||
1011 | (*info).revision = "1.0"; | ||
1012 | } | ||
1013 | |||
1014 | long ata_last_disk_activity(void) | ||
1015 | { | ||
1016 | return ata_last_activity_value; | ||
1017 | } | ||
1018 | |||
1019 | #ifdef ATA_HAVE_BBT | ||
1020 | void ata_bbt_disable(void) | ||
1021 | { | ||
1022 | mutex_lock(&ata_mutex); | ||
1023 | if (ata_bbt) free(ata_bbt); | ||
1024 | ata_bbt = NULL; | ||
1025 | ata_virtual_sectors = ata_total_sectors; | ||
1026 | mutex_unlock(&ata_mutex); | ||
1027 | } | ||
1028 | |||
1029 | void ata_bbt_reload(void) | ||
1030 | { | ||
1031 | mutex_lock(&ata_mutex); | ||
1032 | ata_bbt_disable(); | ||
1033 | ata_power_up(); | ||
1034 | uint32_t* buf = (uint32_t*)(ata_bbt_buf + sizeof(ata_bbt_buf) - SECTOR_SIZE); | ||
1035 | if (buf) | ||
1036 | { | ||
1037 | if (IS_ERR(ata_bbt_read_sectors(0, 1, buf))) | ||
1038 | ata_virtual_sectors = ata_total_sectors; | ||
1039 | else if (!memcmp(buf, "emBIbbth", 8)) | ||
1040 | { | ||
1041 | ata_virtual_sectors = (((uint64_t)buf[0x1fd]) << 32) | buf[0x1fc]; | ||
1042 | uint32_t count = buf[0x1ff]; | ||
1043 | if (count > ATA_BBT_PAGES / 64) | ||
1044 | panicf("ATA: BBT too big! (space: %d, size: %d)", ATA_BBT_PAGES, count * 64); | ||
1045 | uint32_t i; | ||
1046 | uint32_t cnt; | ||
1047 | ata_bbt = (typeof(ata_bbt))ata_bbt_buf; | ||
1048 | for (i = 0; i < count; i += cnt) | ||
1049 | { | ||
1050 | uint32_t phys = buf[0x200 + i]; | ||
1051 | for (cnt = 1; cnt < count; cnt++) | ||
1052 | if (buf[0x200 + i + cnt] != phys + cnt) | ||
1053 | break; | ||
1054 | if (IS_ERR(ata_bbt_read_sectors(phys, cnt, ata_bbt[i << 6]))) | ||
1055 | { | ||
1056 | ata_virtual_sectors = ata_total_sectors; | ||
1057 | break; | ||
1058 | } | ||
1059 | } | ||
1060 | } | ||
1061 | else ata_virtual_sectors = ata_total_sectors; | ||
1062 | } | ||
1063 | else ata_virtual_sectors = ata_total_sectors; | ||
1064 | mutex_unlock(&ata_mutex); | ||
1065 | } | ||
1066 | #endif | ||
1067 | |||
1068 | int ata_init(void) | ||
1069 | { | ||
1070 | mutex_init(&ata_mutex); | ||
1071 | wakeup_init(&ata_wakeup); | ||
1072 | wakeup_init(&mmc_wakeup); | ||
1073 | wakeup_init(&mmc_comp_wakeup); | ||
1074 | ceata = PDAT(11) & BIT(1); | ||
1075 | if (ceata) | ||
1076 | { | ||
1077 | ata_lba48 = true; | ||
1078 | ata_dma = true; | ||
1079 | PCON(8) = 0x33333333; | ||
1080 | PCON(9) = (PCON(9) & ~0xff) | 0x33; | ||
1081 | PCON(11) |= 0xf; | ||
1082 | *((uint32_t volatile*)0x38a00000) = 0; | ||
1083 | *((uint32_t volatile*)0x38700000) = 0; | ||
1084 | } | ||
1085 | else | ||
1086 | { | ||
1087 | PCON(7) = 0x44444444; | ||
1088 | PCON(8) = 0x44444444; | ||
1089 | PCON(9) = 0x44444444; | ||
1090 | PCON(10) = (PCON(10) & ~0xffff) | 0x4444; | ||
1091 | } | ||
1092 | ata_powered = false; | ||
1093 | ata_total_sectors = 0; | ||
1094 | ata_power_up(); | ||
1095 | #ifdef ATA_HAVE_BBT | ||
1096 | ata_bbt_reload(); | ||
1097 | #endif | ||
1098 | create_thread(ata_thread, ata_stack, | ||
1099 | sizeof(ata_stack), 0, "ATA idle monitor" | ||
1100 | IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
1101 | IF_COP(, CPU)); | ||
1102 | return 0; | ||
1103 | } | ||
1104 | |||
1105 | int ata_num_drives(int first_drive) | ||
1106 | { | ||
1107 | /* We don't care which logical drive number(s) we have been assigned */ | ||
1108 | (void)first_drive; | ||
1109 | |||
1110 | return 1; | ||
1111 | } | ||
1112 | |||
1113 | unsigned short* ata_get_identify(void) | ||
1114 | { | ||
1115 | return ata_identify_data; | ||
1116 | } | ||
1117 | |||
1118 | int ata_spinup_time(void) | ||
1119 | { | ||
1120 | return spinup_time; | ||
1121 | } | ||
1122 | |||
1123 | int ata_get_dma_mode(void) | ||
1124 | { | ||
1125 | return dma_mode; | ||
1126 | } | ||
1127 | |||
1128 | void INT_ATA(void) | ||
1129 | { | ||
1130 | uint32_t ata_irq = ATA_IRQ; | ||
1131 | ATA_IRQ = ata_irq; | ||
1132 | if (ata_irq & ATA_IRQ_MASK) wakeup_signal(&ata_wakeup); | ||
1133 | ATA_IRQ_MASK = 0; | ||
1134 | } | ||
1135 | |||
1136 | void INT_MMC(void) | ||
1137 | { | ||
1138 | uint32_t irq = SDCI_IRQ; | ||
1139 | if (irq & SDCI_IRQ_DAT_DONE_INT) wakeup_signal(&mmc_wakeup); | ||
1140 | if (irq & SDCI_IRQ_IOCARD_IRQ_INT) wakeup_signal(&mmc_comp_wakeup); | ||
1141 | SDCI_IRQ = irq; | ||
1142 | } | ||
diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c index 4a8f47e59e..e264e61e22 100644 --- a/firmware/target/arm/s5l8702/system-s5l8702.c +++ b/firmware/target/arm/s5l8702/system-s5l8702.c | |||
@@ -97,7 +97,7 @@ default_interrupt(INT_IRQ40); | |||
97 | default_interrupt(INT_IRQ41); | 97 | default_interrupt(INT_IRQ41); |
98 | default_interrupt(INT_IRQ42); | 98 | default_interrupt(INT_IRQ42); |
99 | default_interrupt(INT_IRQ43); | 99 | default_interrupt(INT_IRQ43); |
100 | default_interrupt(INT_IRQ44); | 100 | default_interrupt(INT_MMC); |
101 | default_interrupt(INT_IRQ45); | 101 | default_interrupt(INT_IRQ45); |
102 | default_interrupt(INT_IRQ46); | 102 | default_interrupt(INT_IRQ46); |
103 | default_interrupt(INT_IRQ47); | 103 | default_interrupt(INT_IRQ47); |
@@ -169,7 +169,7 @@ static void (* const irqvector[])(void) = | |||
169 | INT_DMAC0,INT_DMAC1,INT_IRQ18,INT_USB_FUNC,INT_IRQ20,INT_IRQ21,INT_IRQ22,INT_WHEEL, | 169 | INT_DMAC0,INT_DMAC1,INT_IRQ18,INT_USB_FUNC,INT_IRQ20,INT_IRQ21,INT_IRQ22,INT_WHEEL, |
170 | INT_IRQ24,INT_IRQ25,INT_IRQ26,INT_IRQ27,INT_IRQ28,INT_ATA,INT_IRQ30,INT_IRQ31, | 170 | INT_IRQ24,INT_IRQ25,INT_IRQ26,INT_IRQ27,INT_IRQ28,INT_ATA,INT_IRQ30,INT_IRQ31, |
171 | INT_IRQ32,INT_IRQ33,INT_IRQ34,INT_IRQ35,INT_IRQ36,INT_IRQ37,INT_IRQ38,INT_IRQ39, | 171 | INT_IRQ32,INT_IRQ33,INT_IRQ34,INT_IRQ35,INT_IRQ36,INT_IRQ37,INT_IRQ38,INT_IRQ39, |
172 | INT_IRQ40,INT_IRQ41,INT_IRQ42,INT_IRQ43,INT_IRQ55,INT_IRQ56,INT_IRQ57,INT_IRQ58, | 172 | INT_IRQ40,INT_IRQ41,INT_IRQ42,INT_IRQ43,INT_MMC,INT_IRQ45,INT_IRQ46,INT_IRQ47, |
173 | INT_IRQ48,INT_IRQ49,INT_IRQ50,INT_IRQ51,INT_IRQ52,INT_IRQ53,INT_IRQ54,INT_IRQ55, | 173 | INT_IRQ48,INT_IRQ49,INT_IRQ50,INT_IRQ51,INT_IRQ52,INT_IRQ53,INT_IRQ54,INT_IRQ55, |
174 | INT_IRQ56,INT_IRQ57,INT_IRQ58,INT_IRQ59,INT_IRQ60,INT_IRQ61,INT_IRQ62,INT_IRQ63 | 174 | INT_IRQ56,INT_IRQ57,INT_IRQ58,INT_IRQ59,INT_IRQ60,INT_IRQ61,INT_IRQ62,INT_IRQ63 |
175 | }; | 175 | }; |
@@ -218,6 +218,8 @@ void system_init(void) | |||
218 | { | 218 | { |
219 | pmu_init(); | 219 | pmu_init(); |
220 | VIC0INTENABLE = 1 << IRQ_WHEEL; | 220 | VIC0INTENABLE = 1 << IRQ_WHEEL; |
221 | VIC0INTENABLE = 1 << IRQ_ATA; | ||
222 | VIC1INTENABLE = 1 << (IRQ_MMC - 32); | ||
221 | } | 223 | } |
222 | 224 | ||
223 | void system_reboot(void) | 225 | void system_reboot(void) |