summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2008-12-04 20:48:19 +0000
committerRafaël Carré <rafael.carre@gmail.com>2008-12-04 20:48:19 +0000
commit1ab08e6879b1fe50102fe68a1326db05891e6faa (patch)
treeb066febe812ae945fe1c91781338b0334edf0a00
parent76617c8f9444bfc24744e6e4faeff06d25372fa8 (diff)
downloadrockbox-1ab08e6879b1fe50102fe68a1326db05891e6faa.tar.gz
rockbox-1ab08e6879b1fe50102fe68a1326db05891e6faa.tar.bz2
rockbox-1ab08e6879b1fe50102fe68a1326db05891e6faa.zip
Sansa AMS: updates DMA API
* Adds a callback to be called on end of transfer * Add a function to disable a channel * Services the 2 channels if both are active in the isr SD driver: panics on error git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19333 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/as3525/ata_sd_as3525.c49
-rw-r--r--firmware/target/arm/as3525/dma-pl081.c29
-rw-r--r--firmware/target/arm/as3525/dma-target.h4
3 files changed, 68 insertions, 14 deletions
diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c
index b2d8e3c1f3..3ec1892542 100644
--- a/firmware/target/arm/as3525/ata_sd_as3525.c
+++ b/firmware/target/arm/as3525/ata_sd_as3525.c
@@ -129,6 +129,37 @@ static void mci_set_clock_divider(const int drive, int divider)
mci_delay();
}
+static void sd_panic(IF_MV2(const int drive,) const int status)
+{
+ char error[32];
+ error[0] = '\0';
+
+#ifdef HAVE_MULTIVOLUME
+ snprintf(error, sizeof(error),
+ (drive == INTERNAL_AS3525) ? "Internal storage : " : "SD Slot : " );
+#endif
+
+ panicf("SD : %s%s%s%s%s%s%s", error,
+ (status & MCI_DATA_CRC_FAIL) ? "DATA CRC FAIL, " : "",
+ (status & MCI_DATA_TIMEOUT) ? "DATA TIMEOUT, " : "",
+ (status & MCI_RX_OVERRUN) ? "RX OVERRUN, " : "",
+ (status & MCI_TX_UNDERRUN) ? "TX UNDERRUN, " : "",
+ (status & MCI_RX_FIFO_FULL) ? "RXR FIFO FULL, " : "",
+ (status & MCI_TX_FIFO_EMPTY) ? "TX FIFO EMPTY" : "");
+}
+
+void INT_NAND(void)
+{
+ sd_panic(IF_MV2(INTERNAL_AS3525,) MCI_STATUS(INTERNAL_AS3525));
+}
+
+#ifdef HAVE_MULTIVOLUME
+void INT_MCI0(void)
+{
+ sd_panic(SD_SLOT_AS3525, MCI_STATUS(SD_SLOT_AS3525));
+}
+#endif
+
static bool send_cmd(const int drive, const int cmd, const int arg,
const int flags, int *response)
{
@@ -362,7 +393,14 @@ static void init_pl180_controller(const int drive)
MCI_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0;
MCI_CLEAR(drive) = 0x7ff;
- MCI_MASK0(drive) = MCI_MASK1(drive) = 0; /* disable all interrupts */
+ MCI_MASK0(drive) = MCI_MASK1(drive) = MCI_DATA_CRC_FAIL | MCI_DATA_TIMEOUT |
+ MCI_RX_OVERRUN | MCI_TX_UNDERRUN | MCI_RX_FIFO_FULL | MCI_TX_FIFO_EMPTY;
+
+ VIC_INT_ENABLE |= INTERRUPT_NAND
+#ifdef HAVE_MULTIVOLUME
+ | INTERRUPT_MCI0
+#endif
+ ;
MCI_POWER(drive) = MCI_POWER_UP|(10 /*voltage*/ << 2); /* use OF voltage */
mci_delay();
@@ -378,7 +416,6 @@ static void init_pl180_controller(const int drive)
/* set MCLK divider */
mci_set_clock_divider(drive,
CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ));
-
}
int sd_init(void)
@@ -552,12 +589,12 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
if(write)
dma_enable_channel(0, 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);
+ (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
+ DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
else
dma_enable_channel(0, MCI_FIFO(drive), buf,
- (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
- DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8);
+ (drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
+ DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);
MCI_DATA_TIMER(drive) = 0x1000000; /* FIXME: arbitrary */
MCI_DATA_LENGTH(drive) = transfer * card_info[drive].block_size;
diff --git a/firmware/target/arm/as3525/dma-pl081.c b/firmware/target/arm/as3525/dma-pl081.c
index fbe488ce05..3de4e73c12 100644
--- a/firmware/target/arm/as3525/dma-pl081.c
+++ b/firmware/target/arm/as3525/dma-pl081.c
@@ -27,6 +27,7 @@
#include "kernel.h"
static struct wakeup transfer_completion_signal[2]; /* 2 channels */
+static void (*dma_callback[2])(void); /* 2 channels */
inline void dma_wait_transfer(int channel)
{
@@ -45,10 +46,17 @@ void dma_init(void)
wakeup_init(&transfer_completion_signal[1]);
}
+inline void dma_disable_channel(int channel)
+{
+ DMAC_CH_CONFIGURATION(channel) &= ~(1<<0);
+}
+
void dma_enable_channel(int channel, void *src, void *dst, int peri,
int flow_controller, bool src_inc, bool dst_inc,
- size_t size, int nwords)
+ size_t size, int nwords, void (*callback)(void))
{
+ dma_callback[channel] = callback;
+
int control = 0;
DMAC_CH_SRC_ADDR(channel) = (int)src;
@@ -92,12 +100,21 @@ void dma_enable_channel(int channel, void *src, void *dst, int peri,
/* isr */
void INT_DMAC(void)
{
- int channel = (DMAC_INT_STATUS & (1<<0)) ? 0 : 1;
+ unsigned int channel;
+
+ /* SD channel is serviced first */
+ for(channel = 0; channel < 2; channel++)
+ if(DMAC_INT_STATUS & (1<<channel))
+ {
+ if(DMAC_INT_ERROR_STATUS & (1<<channel))
+ panicf("DMA error, channel %d", channel);
- if(DMAC_INT_ERROR_STATUS & (1<<channel))
- panicf("DMA error, channel %d", channel);
+ /* clear terminal count interrupt */
+ DMAC_INT_TC_CLEAR |= (1<<channel);
- DMAC_INT_TC_CLEAR |= (1<<channel); /* clear terminal count interrupt */
+ if(dma_callback[channel])
+ dma_callback[channel]();
- wakeup_signal(&transfer_completion_signal[channel]);
+ wakeup_signal(&transfer_completion_signal[channel]);
+ }
}
diff --git a/firmware/target/arm/as3525/dma-target.h b/firmware/target/arm/as3525/dma-target.h
index cd307b7b2a..26037999f0 100644
--- a/firmware/target/arm/as3525/dma-target.h
+++ b/firmware/target/arm/as3525/dma-target.h
@@ -34,6 +34,6 @@
void dma_init(void);
void dma_enable_channel(int channel, void *src, void *dst, int peri,
int flow_controller, bool src_inc, bool dst_inc,
- size_t size, int nwords);
-
+ size_t size, int nwords, void (*callback)(void));
+inline void dma_disable_channel(int channel);
inline void dma_wait_transfer(int channel);