diff options
Diffstat (limited to 'firmware/target/arm/as3525/sd-as3525.c')
-rw-r--r-- | firmware/target/arm/as3525/sd-as3525.c | 138 |
1 files changed, 35 insertions, 103 deletions
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c index 9e4a86acbe..494a76a782 100644 --- a/firmware/target/arm/as3525/sd-as3525.c +++ b/firmware/target/arm/as3525/sd-as3525.c | |||
@@ -89,8 +89,6 @@ | |||
89 | | MCI_CMD_CRC_FAIL) | 89 | | MCI_CMD_CRC_FAIL) |
90 | 90 | ||
91 | #define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) | 91 | #define MCI_FIFO(i) ((unsigned long *) (pl180_base[i]+0x80)) |
92 | |||
93 | #define IDE_INTERFACE_CLK (1<<6) /* non AHB interface */ | ||
94 | /* volumes */ | 92 | /* volumes */ |
95 | #define INTERNAL_AS3525 0 /* embedded SD card */ | 93 | #define INTERNAL_AS3525 0 /* embedded SD card */ |
96 | #define SD_SLOT_AS3525 1 /* SD slot if present */ | 94 | #define SD_SLOT_AS3525 1 /* SD slot if present */ |
@@ -111,8 +109,7 @@ static void init_pl180_controller(const int drive); | |||
111 | 109 | ||
112 | static tCardInfo card_info[NUM_DRIVES]; | 110 | static tCardInfo card_info[NUM_DRIVES]; |
113 | 111 | ||
114 | /* maximum timeouts recommended in the SD Specification v2.00 */ | 112 | /* maximum timeouts recommanded in the SD Specification v2.00 */ |
115 | /* MCI_DATA_TIMER register data timeout in card bus clock periods */ | ||
116 | #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ | 113 | #define SD_MAX_READ_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 100) /* 100 ms */ |
117 | #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ | 114 | #define SD_MAX_WRITE_TIMEOUT ((AS3525_PCLK_FREQ) / 1000 * 250) /* 250 ms */ |
118 | 115 | ||
@@ -146,17 +143,7 @@ static unsigned char *uncached_buffer = AS3525_UNCACHED_ADDR(&aligned_buffer[0]) | |||
146 | 143 | ||
147 | static inline void mci_delay(void) { udelay(1000) ; } | 144 | static inline void mci_delay(void) { udelay(1000) ; } |
148 | 145 | ||
149 | static inline bool card_detect_target(void) | 146 | static void enable_controller(bool on) |
150 | { | ||
151 | #if defined(HAVE_MULTIDRIVE) | ||
152 | return !(GPIOA_PIN(2)); | ||
153 | #else | ||
154 | return false; | ||
155 | #endif | ||
156 | } | ||
157 | |||
158 | #if defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP) | ||
159 | static void enable_controller_mci(bool on) | ||
160 | { | 147 | { |
161 | 148 | ||
162 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) | 149 | #if defined(HAVE_BUTTON_LIGHT) && defined(HAVE_MULTIDRIVE) |
@@ -210,33 +197,17 @@ static void enable_controller_mci(bool on) | |||
210 | #endif | 197 | #endif |
211 | } | 198 | } |
212 | } | 199 | } |
213 | #endif /* defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP) */ | ||
214 | 200 | ||
215 | /* AMS v1 have two different drive interfaces MCI_SD(XPD) and GGU_IDE */ | 201 | static inline bool card_detect_target(void) |
216 | static void enable_controller(bool on, const int drive) | ||
217 | { | 202 | { |
218 | 203 | #if defined(HAVE_MULTIDRIVE) | |
219 | if (drive == INTERNAL_AS3525) | 204 | return !(GPIOA_PIN(2)); |
220 | { | 205 | #else |
221 | #ifndef BOOTLOADER | 206 | return false; |
222 | if (on) | ||
223 | { | ||
224 | bitset32(&CGU_PERI, CGU_NAF_CLOCK_ENABLE); | ||
225 | CGU_IDE |= IDE_INTERFACE_CLK; /* interface enable */ | ||
226 | } | ||
227 | else | ||
228 | { | ||
229 | CGU_IDE &= ~(IDE_INTERFACE_CLK); /* interface disable */ | ||
230 | bitclr32(&CGU_PERI, CGU_NAF_CLOCK_ENABLE); | ||
231 | } | ||
232 | #endif | ||
233 | } | ||
234 | #if defined(HAVE_MULTIDRIVE) || defined(HAVE_HOTSWAP) | ||
235 | else | ||
236 | enable_controller_mci(on); | ||
237 | #endif | 207 | #endif |
238 | } | 208 | } |
239 | 209 | ||
210 | |||
240 | #ifdef HAVE_HOTSWAP | 211 | #ifdef HAVE_HOTSWAP |
241 | static int sd1_oneshot_callback(struct timeout *tmo) | 212 | static int sd1_oneshot_callback(struct timeout *tmo) |
242 | { | 213 | { |
@@ -355,7 +326,6 @@ static bool send_cmd(const int drive, const int cmd, const int arg, | |||
355 | return false; | 326 | return false; |
356 | } | 327 | } |
357 | 328 | ||
358 | /* MCI_CLOCK = MCLK / 2x(ClkDiv[bits 7:0]+1) */ | ||
359 | #define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */ | 329 | #define MCI_FULLSPEED (MCI_CLOCK_ENABLE | MCI_CLOCK_BYPASS) /* MCLK */ |
360 | #define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */ | 330 | #define MCI_HALFSPEED (MCI_CLOCK_ENABLE) /* MCLK/2 */ |
361 | #define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */ | 331 | #define MCI_QUARTERSPEED (MCI_CLOCK_ENABLE | 1) /* MCLK/4 */ |
@@ -375,7 +345,7 @@ static int sd_init_card(const int drive) | |||
375 | /* 100 - 400kHz clock required for Identification Mode */ | 345 | /* 100 - 400kHz clock required for Identification Mode */ |
376 | /* Start of Card Identification Mode ************************************/ | 346 | /* Start of Card Identification Mode ************************************/ |
377 | 347 | ||
378 | /* CMD0 Go Idle -- all card functions switch back to default */ | 348 | /* CMD0 Go Idle */ |
379 | if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) | 349 | if(!send_cmd(drive, SD_GO_IDLE_STATE, 0, MCI_NO_RESP, NULL)) |
380 | return -1; | 350 | return -1; |
381 | mci_delay(); | 351 | mci_delay(); |
@@ -423,10 +393,10 @@ static int sd_init_card(const int drive) | |||
423 | 393 | ||
424 | if(sd_wait_for_tran_state(drive)) | 394 | if(sd_wait_for_tran_state(drive)) |
425 | return -6; | 395 | return -6; |
426 | /* CMD6 0xf indicates no influence, [3:0],0x1 - HS Access*/ | 396 | /* CMD6 */ |
427 | if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) | 397 | if(!send_cmd(drive, SD_SWITCH_FUNC, 0x80fffff1, MCI_NO_RESP, NULL)) |
428 | return -7; | 398 | return -7; |
429 | sleep(HZ/10);/* need to wait at least 8 clock periods */ | 399 | sleep(HZ/10); |
430 | 400 | ||
431 | /* go back to STBY state so we can read csd */ | 401 | /* go back to STBY state so we can read csd */ |
432 | /* CMD7 w/rca=0: Deselect card to put it in STBY state */ | 402 | /* CMD7 w/rca=0: Deselect card to put it in STBY state */ |
@@ -547,7 +517,7 @@ static void init_pl180_controller(const int drive) | |||
547 | int sd_init(void) | 517 | int sd_init(void) |
548 | { | 518 | { |
549 | int ret; | 519 | int ret; |
550 | CGU_IDE = IDE_INTERFACE_CLK /* enable interface */ | 520 | CGU_IDE = (1<<6) /* enable non AHB interface*/ |
551 | | (AS3525_IDE_DIV << 2) | 521 | | (AS3525_IDE_DIV << 2) |
552 | | AS3525_CLK_PLLA; /* clock source = PLLA */ | 522 | | AS3525_CLK_PLLA; /* clock source = PLLA */ |
553 | 523 | ||
@@ -570,9 +540,7 @@ int sd_init(void) | |||
570 | /* init mutex */ | 540 | /* init mutex */ |
571 | mutex_init(&sd_mtx); | 541 | mutex_init(&sd_mtx); |
572 | 542 | ||
573 | for (int i = 0; i < NUM_DRIVES ; i++) | 543 | enable_controller(false); |
574 | enable_controller(false, i); | ||
575 | |||
576 | return 0; | 544 | return 0; |
577 | } | 545 | } |
578 | 546 | ||
@@ -688,7 +656,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
688 | unsigned long response; | 656 | unsigned long response; |
689 | bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); | 657 | bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); |
690 | 658 | ||
691 | enable_controller(true, drive); | 659 | enable_controller(true); |
692 | led(true); | 660 | led(true); |
693 | 661 | ||
694 | if (card_info[drive].initialized <= 0) | 662 | if (card_info[drive].initialized <= 0) |
@@ -724,21 +692,27 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
724 | else | 692 | else |
725 | discard_dcache_range(buf, count * SECTOR_SIZE); | 693 | discard_dcache_range(buf, count * SECTOR_SIZE); |
726 | } | 694 | } |
727 | const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; | 695 | |
728 | while(count > 0) | 696 | while(count) |
729 | { | 697 | { |
730 | /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH | 698 | /* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH |
731 | * register, so we have to transfer maximum 127 sectors at a time. */ | 699 | * register, so we have to transfer maximum 127 sectors at a time. */ |
732 | unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ | 700 | unsigned int transfer = (count >= 128) ? 127 : count; /* sectors */ |
733 | void *dma_buf; | 701 | void *dma_buf; |
734 | 702 | const int cmd = | |
703 | write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; | ||
735 | unsigned long bank_start = start; | 704 | unsigned long bank_start = start; |
705 | unsigned long status; | ||
736 | 706 | ||
737 | /* Only switch banks for internal storage */ | 707 | /* Only switch banks for internal storage */ |
738 | if(drive == INTERNAL_AS3525) | 708 | if(drive == INTERNAL_AS3525) |
739 | { | 709 | { |
740 | unsigned int bank = bank_start / BLOCKS_PER_BANK; | 710 | unsigned int bank = 0; |
741 | bank_start -= bank * BLOCKS_PER_BANK; | 711 | while(bank_start >= BLOCKS_PER_BANK) |
712 | { | ||
713 | bank_start -= BLOCKS_PER_BANK; | ||
714 | bank++; | ||
715 | } | ||
742 | 716 | ||
743 | /* Switch bank if needed */ | 717 | /* Switch bank if needed */ |
744 | if(card_info[INTERNAL_AS3525].current_bank != bank) | 718 | if(card_info[INTERNAL_AS3525].current_bank != bank) |
@@ -796,7 +770,10 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
796 | /*Small delay for writes prevents data crc failures at lower freqs*/ | 770 | /*Small delay for writes prevents data crc failures at lower freqs*/ |
797 | #ifdef HAVE_MULTIDRIVE | 771 | #ifdef HAVE_MULTIDRIVE |
798 | if((drive == SD_SLOT_AS3525) && !hs_card) | 772 | if((drive == SD_SLOT_AS3525) && !hs_card) |
799 | udelay(4); | 773 | { |
774 | int write_delay = 125; | ||
775 | while(write_delay--); | ||
776 | } | ||
800 | #endif | 777 | #endif |
801 | } | 778 | } |
802 | else | 779 | else |
@@ -827,7 +804,7 @@ static int sd_transfer_sectors(IF_MD(int drive,) unsigned long start, | |||
827 | 804 | ||
828 | last_disk_activity = current_tick; | 805 | last_disk_activity = current_tick; |
829 | 806 | ||
830 | if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP, &response)) | 807 | if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP, &status)) |
831 | { | 808 | { |
832 | ret = -4*20; | 809 | ret = -4*20; |
833 | goto sd_transfer_error; | 810 | goto sd_transfer_error; |
@@ -854,7 +831,7 @@ sd_transfer_error: | |||
854 | sd_transfer_error_nodma: | 831 | sd_transfer_error_nodma: |
855 | 832 | ||
856 | led(false); | 833 | led(false); |
857 | enable_controller(false, drive); | 834 | enable_controller(false); |
858 | 835 | ||
859 | if (ret) /* error */ | 836 | if (ret) /* error */ |
860 | card_info[drive].initialized = 0; | 837 | card_info[drive].initialized = 0; |
@@ -945,18 +922,12 @@ void ams_sd_get_debug_info(struct ams_sd_debug_info *info) | |||
945 | #define MCI_SD *((volatile unsigned long *)(SD_MCI_BASE + 0x04)) | 922 | #define MCI_SD *((volatile unsigned long *)(SD_MCI_BASE + 0x04)) |
946 | 923 | ||
947 | mutex_lock(&sd_mtx); | 924 | mutex_lock(&sd_mtx); |
948 | 925 | enable_controller(true); /* must be on to read regs */ | |
949 | for (int i = 0; i < NUM_DRIVES ; i++) | ||
950 | enable_controller(true, i); /* must be on to read regs */ | ||
951 | |||
952 | info->mci_nand = MCI_NAND; | 926 | info->mci_nand = MCI_NAND; |
953 | #ifdef HAVE_MULTIDRIVE | 927 | #ifdef HAVE_MULTIDRIVE |
954 | info->mci_sd = MCI_SD; | 928 | info->mci_sd = MCI_SD; |
955 | #endif | 929 | #endif |
956 | 930 | enable_controller(false); | |
957 | for (int i = 0; i < NUM_DRIVES ; i++) | ||
958 | enable_controller(false, i); | ||
959 | |||
960 | mutex_unlock(&sd_mtx); | 931 | mutex_unlock(&sd_mtx); |
961 | } | 932 | } |
962 | 933 | ||
@@ -977,10 +948,10 @@ int sd_event(long id, intptr_t data) | |||
977 | 948 | ||
978 | if (id == SYS_HOTSWAP_INSERTED) | 949 | if (id == SYS_HOTSWAP_INSERTED) |
979 | { | 950 | { |
980 | enable_controller(true, data); | 951 | enable_controller(true); |
981 | init_pl180_controller(data); | 952 | init_pl180_controller(data); |
982 | rc = sd_init_card(data); | 953 | rc = sd_init_card(data); |
983 | enable_controller(false, data); | 954 | enable_controller(false); |
984 | } | 955 | } |
985 | 956 | ||
986 | mutex_unlock(&sd_mtx); | 957 | mutex_unlock(&sd_mtx); |
@@ -997,42 +968,3 @@ int sd_event(long id, intptr_t data) | |||
997 | 968 | ||
998 | return rc; | 969 | return rc; |
999 | } | 970 | } |
1000 | |||
1001 | #if defined(CONFIG_POWER_SAVING) && (CONFIG_POWER_SAVING & POWERSV_DISK) | ||
1002 | /* declared in system-as3525.c */ | ||
1003 | void ams_sd_set_low_speed(bool slow) | ||
1004 | { | ||
1005 | /* block access while speed is changed */ | ||
1006 | mutex_lock(&sd_mtx); | ||
1007 | enable_controller(true, INTERNAL_AS3525); | ||
1008 | |||
1009 | /* After a data write, data cannot be written to MCI_CLOCK | ||
1010 | for 3 MCLK periods + 2 PCLK periods. ~10us worst case | ||
1011 | */ | ||
1012 | udelay(100); | ||
1013 | if (slow) | ||
1014 | { | ||
1015 | /* only affects internal drive clock speed*/ | ||
1016 | CGU_IDE = (CGU_IDE & ~(0xF << 2)) | (AS3525_IDE_DIV_MAX << 2); | ||
1017 | /* power save is enabled for the sd card(s) */ | ||
1018 | for (int i = 0; i < NUM_DRIVES ; i++) | ||
1019 | { | ||
1020 | if (i != INTERNAL_AS3525 && (MCI_CLOCK(i) & MCI_CLOCK_POWERSAVE) == 0) | ||
1021 | MCI_CLOCK(i) |= MCI_CLOCK_POWERSAVE; | ||
1022 | } | ||
1023 | } | ||
1024 | else | ||
1025 | { | ||
1026 | /* Full Speed */ | ||
1027 | CGU_IDE = (CGU_IDE & ~(0xF << 2)) | (AS3525_IDE_DIV << 2); | ||
1028 | for (int i = 0; i < NUM_DRIVES ; i++) | ||
1029 | { | ||
1030 | if (i != INTERNAL_AS3525 && (MCI_CLOCK(i) & MCI_CLOCK_POWERSAVE) != 0) | ||
1031 | MCI_CLOCK(i) = (MCI_CLOCK(i) & ~MCI_CLOCK_POWERSAVE); | ||
1032 | } | ||
1033 | } | ||
1034 | enable_controller(false, INTERNAL_AS3525); | ||
1035 | mutex_unlock(&sd_mtx); | ||
1036 | } | ||
1037 | #endif | ||
1038 | |||