mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 13:15:18 -05:00
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
This commit is contained in:
parent
76617c8f94
commit
1ab08e6879
3 changed files with 68 additions and 14 deletions
|
|
@ -129,6 +129,37 @@ static void mci_set_clock_divider(const int drive, int divider)
|
||||||
mci_delay();
|
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,
|
static bool send_cmd(const int drive, const int cmd, const int arg,
|
||||||
const int flags, int *response)
|
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_COMMAND(drive) = MCI_DATA_CTRL(drive) = 0;
|
||||||
MCI_CLEAR(drive) = 0x7ff;
|
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_POWER(drive) = MCI_POWER_UP|(10 /*voltage*/ << 2); /* use OF voltage */
|
||||||
mci_delay();
|
mci_delay();
|
||||||
|
|
@ -378,7 +416,6 @@ static void init_pl180_controller(const int drive)
|
||||||
/* set MCLK divider */
|
/* set MCLK divider */
|
||||||
mci_set_clock_divider(drive,
|
mci_set_clock_divider(drive,
|
||||||
CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ));
|
CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_init(void)
|
int sd_init(void)
|
||||||
|
|
@ -552,12 +589,12 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
|
||||||
|
|
||||||
if(write)
|
if(write)
|
||||||
dma_enable_channel(0, buf, MCI_FIFO(drive),
|
dma_enable_channel(0, buf, MCI_FIFO(drive),
|
||||||
(drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
|
(drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
|
||||||
DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8);
|
DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
|
||||||
else
|
else
|
||||||
dma_enable_channel(0, MCI_FIFO(drive), buf,
|
dma_enable_channel(0, MCI_FIFO(drive), buf,
|
||||||
(drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
|
(drive == INTERNAL_AS3525) ? DMA_PERI_SD : DMA_PERI_SD_SLOT,
|
||||||
DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8);
|
DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);
|
||||||
|
|
||||||
MCI_DATA_TIMER(drive) = 0x1000000; /* FIXME: arbitrary */
|
MCI_DATA_TIMER(drive) = 0x1000000; /* FIXME: arbitrary */
|
||||||
MCI_DATA_LENGTH(drive) = transfer * card_info[drive].block_size;
|
MCI_DATA_LENGTH(drive) = transfer * card_info[drive].block_size;
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
|
||||||
static struct wakeup transfer_completion_signal[2]; /* 2 channels */
|
static struct wakeup transfer_completion_signal[2]; /* 2 channels */
|
||||||
|
static void (*dma_callback[2])(void); /* 2 channels */
|
||||||
|
|
||||||
inline void dma_wait_transfer(int channel)
|
inline void dma_wait_transfer(int channel)
|
||||||
{
|
{
|
||||||
|
|
@ -45,10 +46,17 @@ void dma_init(void)
|
||||||
wakeup_init(&transfer_completion_signal[1]);
|
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,
|
void dma_enable_channel(int channel, void *src, void *dst, int peri,
|
||||||
int flow_controller, bool src_inc, bool dst_inc,
|
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;
|
int control = 0;
|
||||||
|
|
||||||
DMAC_CH_SRC_ADDR(channel) = (int)src;
|
DMAC_CH_SRC_ADDR(channel) = (int)src;
|
||||||
|
|
@ -92,12 +100,21 @@ void dma_enable_channel(int channel, void *src, void *dst, int peri,
|
||||||
/* isr */
|
/* isr */
|
||||||
void INT_DMAC(void)
|
void INT_DMAC(void)
|
||||||
{
|
{
|
||||||
int channel = (DMAC_INT_STATUS & (1<<0)) ? 0 : 1;
|
unsigned int channel;
|
||||||
|
|
||||||
if(DMAC_INT_ERROR_STATUS & (1<<channel))
|
/* SD channel is serviced first */
|
||||||
panicf("DMA error, channel %d", channel);
|
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);
|
||||||
|
|
||||||
DMAC_INT_TC_CLEAR |= (1<<channel); /* clear terminal count interrupt */
|
/* clear terminal count interrupt */
|
||||||
|
DMAC_INT_TC_CLEAR |= (1<<channel);
|
||||||
|
|
||||||
wakeup_signal(&transfer_completion_signal[channel]);
|
if(dma_callback[channel])
|
||||||
|
dma_callback[channel]();
|
||||||
|
|
||||||
|
wakeup_signal(&transfer_completion_signal[channel]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,6 @@
|
||||||
void dma_init(void);
|
void dma_init(void);
|
||||||
void dma_enable_channel(int channel, void *src, void *dst, int peri,
|
void dma_enable_channel(int channel, void *src, void *dst, int peri,
|
||||||
int flow_controller, bool src_inc, bool dst_inc,
|
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);
|
inline void dma_wait_transfer(int channel);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue