diff options
| author | Rafaël Carré <rafael.carre@gmail.com> | 2008-12-04 20:48:19 +0000 |
|---|---|---|
| committer | Rafaël Carré <rafael.carre@gmail.com> | 2008-12-04 20:48:19 +0000 |
| commit | 1ab08e6879b1fe50102fe68a1326db05891e6faa (patch) | |
| tree | b066febe812ae945fe1c91781338b0334edf0a00 | |
| parent | 76617c8f9444bfc24744e6e4faeff06d25372fa8 (diff) | |
| download | rockbox-1ab08e6879b1fe50102fe68a1326db05891e6faa.zip rockbox-1ab08e6879b1fe50102fe68a1326db05891e6faa.tar.gz rockbox-1ab08e6879b1fe50102fe68a1326db05891e6faa.tar.bz2 rockbox-1ab08e6879b1fe50102fe68a1326db05891e6faa.tar.xz | |
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.c | 49 | ||||
| -rw-r--r-- | firmware/target/arm/as3525/dma-pl081.c | 29 | ||||
| -rw-r--r-- | firmware/target/arm/as3525/dma-target.h | 4 |
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 b2d8e3c..3ec1892 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 fbe488c..3de4e73 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 cd307b7..2603799 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); |