summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/as3525')
-rw-r--r--firmware/target/arm/as3525/ata_sd_as3525.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c
index 43c1a37670..d59777a57d 100644
--- a/firmware/target/arm/as3525/ata_sd_as3525.c
+++ b/firmware/target/arm/as3525/ata_sd_as3525.c
@@ -336,9 +336,6 @@ static int sd_init_card(const int drive)
}
#endif /* HAVE_MULTIDRIVE */
- /* Boost MCICLK to operating speed */ /*FIXME: v1 at 31 MHz still too high*/
- MCI_CLOCK(drive) = (sd_v2 ? MCI_HALFSPEED : MCI_HALFSPEED);
-
/* CMD9 send CSD */
if(!send_cmd(drive, SD_SEND_CSD, card_info[drive].rca,
MCI_RESP|MCI_LONG_RESP|MCI_ARG, temp_reg))
@@ -349,6 +346,14 @@ static int sd_init_card(const int drive)
sd_parse_csd(&card_info[drive]);
+ /* Boost MCICLK to operating speed */
+ if(drive == INTERNAL_AS3525)
+ MCI_CLOCK(drive) = MCI_QUARTERSPEED; /* MCICLK = PCLK/4 = 15.5MHz */
+ else
+ /* MCICLK = PCLK/2 = 31MHz(HS) or PCLK/4 = 15.5 Mhz (STD)*/
+ MCI_CLOCK(drive) = ((card_info[drive].speed == 50000000) ?
+ MCI_HALFSPEED : MCI_QUARTERSPEED);
+
/* CMD7 w/rca: Select card to put it in TRAN state */
if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_ARG, NULL))
return -10;
@@ -619,6 +624,7 @@ static int sd_select_bank(signed char bank)
(1<<3) /* DMA */ |
(9<<4) /* 2^9 = 512 */ ;
+ /* Wakeup signal comes from NAND/MCIO isr on MCI_ERROR | MCI_DATA_END */
wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
/* Wait for FIFO to empty, card may still be in PRG state */
@@ -697,16 +703,17 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
transfer = BLOCKS_PER_BANK - bank_start;
}
+ /* Set bank_start to the correct unit (blocks or bytes) */
+ if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */
+ bank_start *= SD_BLOCK_SIZE;
+
dma_buf = aligned_buffer;
if(transfer > UNALIGNED_NUM_SECTORS)
transfer = UNALIGNED_NUM_SECTORS;
+
if(write)
memcpy(uncached_buffer, buf, transfer * SD_BLOCK_SIZE);
- /* Set bank_start to the correct unit (blocks or bytes) */
- if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */
- bank_start *= SD_BLOCK_SIZE;
-
ret = sd_wait_for_state(drive, SD_TRAN);
if (ret < 0)
{
@@ -721,17 +728,20 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
}
if(write)
+ {
dma_enable_channel(0, dma_buf, MCI_FIFO(drive),
(drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
+
+ /*Small delay for writes prevents data crc failures at lower freqs*/
+ int write_delay = 125;
+ while(write_delay--);
+ }
else
dma_enable_channel(0, MCI_FIFO(drive), dma_buf,
(drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);
- /* FIXME : we should check if the timeouts calculated from the card's
- * CSD are lower, and use them if it is the case
- * Note : the OF doesn't seem to use them anyway */
MCI_DATA_TIMER(drive) = write ?
SD_MAX_WRITE_TIMEOUT : SD_MAX_READ_TIMEOUT;
MCI_DATA_LENGTH(drive) = transfer * SD_BLOCK_SIZE;
@@ -740,6 +750,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
(1<<3) /* DMA */ |
(9<<4) /* 2^9 = 512 */ ;
+ /* Wakeup signal comes from NAND/MCIO isr on MCI_ERROR | MCI_DATA_END */
wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
/* Wait for FIFO to empty, card may still be in PRG state for writes */