summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2011-08-08 20:09:27 +0000
committerMarcin Bukat <marcin.bukat@gmail.com>2011-08-08 20:09:27 +0000
commit1d2fae446699fbb7697b070fba9352cd4a3af53f (patch)
tree7fd70af355460a97ec97290866aca85bb92d4b54 /firmware
parentc23f576a1cadc88d305ad04be039a2438eb85e14 (diff)
rk27xx sd driver fixes
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30269 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/rk27xx/sd-rk27xx.c125
1 files changed, 76 insertions, 49 deletions
diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c
index c5a23ad00d..dab6c3e1f3 100644
--- a/firmware/target/arm/rk27xx/sd-rk27xx.c
+++ b/firmware/target/arm/rk27xx/sd-rk27xx.c
@@ -457,73 +457,90 @@ int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count,
ret = 0;
retry = false; /* reset retry flag */
- mmu_buff_reset(); /* reset recive buff state */
+
+ mmu_buff_reset();
+
+ if (cnt == 1)
+ {
+ /* last block to tranfer */
+ SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
+ DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
+ DATA_XFER_SINGLE;
+ }
+ else
+ {
+ /* more than one block to transfer */
+ SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
+ DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
+ DATA_XFER_MULTI;
+ }
/* issue read command to the card */
if (!send_cmd(SD_READ_MULTIPLE_BLOCK, start, RES_R1, &response))
{
- ret = -4;
+ ret = -2;
continue;
}
while (cnt > 0)
{
- if (cnt == 1)
- {
- /* last block to tranfer */
- SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
- DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
- DATA_XFER_SINGLE;
- }
- else
- {
- /* more than one block to transfer */
- SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
- DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
- DATA_XFER_MULTI;
- }
-
/* wait for transfer completion */
semaphore_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
if (retry)
{
/* data transfer error */
- ret = -5;
+ ret = -3;
break;
}
/* exchange buffers */
mmu_switch_buff();
- last_disk_activity = current_tick;
-
- /* transfer data from receive buffer to the dest
- * for (i=0; i<(512/4); i++)
- * *dst++ = MMU_DATA;
- *
- * below is DMA version in software mode.
- * SD module provides DMAreq signals and all this
- * can be done in hardware in theory but I can't
- * figure this out. OF doesn't use DMA at all.
- */
A2A_IDST0 = (unsigned long)dst;
- A2A_CON0 = (3<<9) | (1<<6) | (1<<3) | (2<<1) | (1<<0);
+ A2A_CON0 = (3<<9) | /* burst 16 */
+ (1<<6) | /* fixed src */
+ (1<<3) | /* DMA start */
+ (2<<1) | /* word transfer size */
+ (1<<0); /* software mode */
/* wait for DMA engine to finish transfer */
while (A2A_DMA_STS & 1);
dst += 512;
cnt--;
- } /* while (cnt > 0) */
- if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response))
- ret = -6;
+ if (cnt == 0)
+ {
+ if (!send_cmd(SD_STOP_TRANSMISSION, 0, RES_R1b, &response))
+ ret = -4;
+
+ break;
+ }
+ else if (cnt == 1)
+ {
+ /* last block to tranfer */
+ SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
+ DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
+ DATA_XFER_SINGLE;
+ }
+ else
+ {
+ /* more than one block to transfer */
+ SD_DATAT = DATA_XFER_START | DATA_XFER_READ |
+ DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
+ DATA_XFER_MULTI;
+ }
+
+ last_disk_activity = current_tick;
+
+ } /* while (cnt > 0) */
/* transfer successfull - leave retry loop */
if (ret == 0)
break;
- }
+
+ } /* while (retry_cnt++ < 20) */
sd_enable(false);
mutex_unlock(&sd_mtx);
@@ -548,7 +565,7 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
unsigned int retry_cnt = 0;
int cnt, ret = 0;
unsigned char *src;
- bool card_selected = false;
+ /* bool card_selected = false; */
mutex_lock(&sd_mtx);
sd_enable(true);
@@ -574,6 +591,18 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
retry = false; /* reset retry flag */
mmu_buff_reset(); /* reset recive buff state */
+ /* transfer data from receive buffer to the dest
+ * for (i=0; i<(512/4); i++)
+ * MMU_DATA = *src++;
+ *
+ * Below is DMA version in software mode.
+ */
+
+ A2A_ISRC0 = (unsigned long)src;
+ A2A_CON0 = (3<<9) | (1<<5) | (1<<3) | (2<<1) | (1<<0);
+
+ while (A2A_DMA_STS & 1);
+
if (!send_cmd(SD_WRITE_MULTIPLE_BLOCK, start, RES_R1, &response))
{
ret = -3;
@@ -582,20 +611,6 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
while (cnt > 0)
{
- /* transfer data from receive buffer to the dest
- * for (i=0; i<(512/4); i++)
- * MMU_DATA = *src++;
- *
- * Below is DMA version in software mode.
- */
-
- A2A_ISRC0 = (unsigned long)src;
- A2A_CON0 = (3<<9) | (1<<5) | (1<<3) | (2<<1) | (1<<0);
-
- while (A2A_DMA_STS & 1);
-
- src += 512;
-
/* exchange buffers */
mmu_switch_buff();
@@ -614,6 +629,18 @@ int sd_write_sectors(IF_MD2(int drive,) unsigned long start, int count,
DATA_BUS_1LINE | DATA_XFER_DMA_DIS |
DATA_XFER_MULTI;
+ /* transfer data from receive buffer to the dest
+ * for (i=0; i<(512/4); i++)
+ * MMU_DATA = *src++;
+ *
+ * Below is DMA version in software mode.
+ */
+ src += 512;
+
+ A2A_ISRC0 = (unsigned long)src;
+ A2A_CON0 = (3<<9) | (1<<5) | (1<<3) | (2<<1) | (1<<0);
+
+ while (A2A_DMA_STS & 1);
}
/* wait for transfer completion */