1
0
Fork 0
forked from len0rd/rockbox

jz4760: Give each SD interface its own DMA channel, semaphore, and mutex

* Allows both SD interfaces to have requests in flight simultaneously
 * Fixed a deadlock in the hotswap code
 * Ensure TX DMA is idle before initiating a request (bug due to a typo)

Change-Id: I988fa29df5f8e41fc6bbdcc517db89842003b34d
This commit is contained in:
Solomon Peachy 2020-08-24 23:34:34 -04:00
parent c06766bbeb
commit 63ef81de31
3 changed files with 175 additions and 91 deletions

View file

@ -30,6 +30,7 @@
#include "storage.h"
#include "string.h"
#define SD_INTERRUPT 0
#define SD_DMA_ENABLE 1
#define SD_DMA_INTERRUPT 0
@ -39,6 +40,7 @@
static long last_disk_activity = -1;
static tCardInfo card[NUM_DRIVES];
static char active[NUM_DRIVES];
#if defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOTSWAP)
static int sd_drive_nr = 0;
@ -46,9 +48,9 @@ static int sd_drive_nr = 0;
#define sd_drive_nr 0
#endif
static struct mutex sd_mtx;
#if SD_DMA_INTERRUPT
static struct semaphore sd_wakeup;
static struct mutex sd_mtx[NUM_DRIVES];
#if SD_DMA_INTERRUPT || SD_INTERRUPT
static struct semaphore sd_wakeup[NUM_DRIVES];
#endif
static int use_4bit[NUM_DRIVES];
@ -382,6 +384,11 @@ static void jz_sd_get_response(const int drive, struct sd_request *request)
}
}
#if SD_DMA_ENABLE
static int jz_sd_transmit_data_dma(const int drive, struct sd_request *req);
static int jz_sd_receive_data_dma(const int drive, struct sd_request *req);
#endif
static int jz_sd_receive_data(const int drive, struct sd_request *req)
{
unsigned int nob = req->nob;
@ -391,6 +398,12 @@ static int jz_sd_receive_data(const int drive, struct sd_request *req)
unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */
unsigned int stat, data, cnt;
#if SD_DMA_ENABLE
/* Use DMA if we can */
if ((int)req->buffer & 0x3 == 0)
return jz_sd_receive_data_dma(drive, req);
#endif
for (; nob >= 1; nob--)
{
long deadline = current_tick + (HZ * 65);
@ -448,6 +461,12 @@ static int jz_sd_transmit_data(const int drive, struct sd_request *req)
unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */
unsigned int stat, data, cnt;
#if SD_DMA_ENABLE
/* Use DMA if we can */
if ((int)req->buffer & 0x3 == 0)
return jz_sd_transmit_data_dma(drive, req);
#endif
for (; nob >= 1; nob--)
{
long deadline = current_tick + (HZ * 65);
@ -498,123 +517,162 @@ static int jz_sd_transmit_data(const int drive, struct sd_request *req)
#if SD_DMA_ENABLE
static int jz_sd_receive_data_dma(const int drive, struct sd_request *req)
{
if ((unsigned int)req->buffer & 0x3)
return jz_sd_receive_data(drive, req);
/* flush dcache */
dma_cache_wback_inv((unsigned long) req->buffer, req->cnt);
/* setup dma channel */
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0;
REG_DMAC_DSAR(DMA_SD_RX_CHANNEL) = PHYSADDR(MSC_RXFIFO(MSC_CHN(drive))); /* DMA source addr */
REG_DMAC_DTAR(DMA_SD_RX_CHANNEL) = PHYSADDR((unsigned long)req->buffer); /* DMA dest addr */
REG_DMAC_DTCR(DMA_SD_RX_CHANNEL) = (req->cnt + 3) >> 2; /* DMA transfer count */
REG_DMAC_DRSR(DMA_SD_RX_CHANNEL) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2IN : DMAC_DRSR_RS_MSC1IN; /* DMA request type */
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(drive)) = 0;
REG_DMAC_DSAR(DMA_SD_RX_CHANNEL(drive)) = PHYSADDR(MSC_RXFIFO(MSC_CHN(drive))); /* DMA source addr */
REG_DMAC_DTAR(DMA_SD_RX_CHANNEL(drive)) = PHYSADDR((unsigned long)req->buffer); /* DMA dest addr */
REG_DMAC_DTCR(DMA_SD_RX_CHANNEL(drive)) = (req->cnt + 3) >> 2; /* DMA transfer count */
REG_DMAC_DRSR(DMA_SD_RX_CHANNEL(drive)) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2IN : DMAC_DRSR_RS_MSC1IN; /* DMA request type */
REG_DMAC_DCMD(DMA_SD_RX_CHANNEL) =
REG_DMAC_DCMD(DMA_SD_RX_CHANNEL(drive)) =
#if SD_DMA_INTERRUPT
DMAC_DCMD_TIE | /* Enable DMA interrupt */
#endif
DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 |
DMAC_DCMD_DS_32BIT;
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES;
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(drive)) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES;
/* wait for dma completion */
#if SD_DMA_INTERRUPT
semaphore_wait(&sd_wakeup, TIMEOUT_BLOCK);
semaphore_wait(&sd_wakeup[drive], TIMEOUT_BLOCK);
#else
while (REG_DMAC_DTCR(DMA_SD_RX_CHANNEL))
while (REG_DMAC_DTCR(DMA_SD_RX_CHANNEL(drive)))
yield();
#endif
/* clear status and disable channel */
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0;
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(drive)) = 0;
/* flush dcache */
dma_cache_wback_inv((unsigned long) req->buffer, req->cnt);
return SD_NO_ERROR;
}
static int jz_sd_transmit_data_dma(const int drive, struct sd_request *req)
{
if ((unsigned int)req->buffer & 0x3)
return jz_sd_transmit_data(drive, req);
/* flush dcache */
dma_cache_wback_inv((unsigned long) req->buffer, req->cnt);
/* setup dma channel */
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0;
REG_DMAC_DSAR(DMA_SD_TX_CHANNEL) = PHYSADDR((unsigned long) req->buffer); /* DMA source addr */
REG_DMAC_DTAR(DMA_SD_TX_CHANNEL) = PHYSADDR(MSC_TXFIFO(MSC_CHN(drive))); /* DMA dest addr */
REG_DMAC_DTCR(DMA_SD_TX_CHANNEL) = (req->cnt + 3) >> 2; /* DMA transfer count */
REG_DMAC_DRSR(DMA_SD_TX_CHANNEL) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2OUT : DMAC_DRSR_RS_MSC1OUT; /* DMA request type */
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(drive)) = 0;
REG_DMAC_DSAR(DMA_SD_TX_CHANNEL(drive)) = PHYSADDR((unsigned long) req->buffer); /* DMA source addr */
REG_DMAC_DTAR(DMA_SD_TX_CHANNEL(drive)) = PHYSADDR(MSC_TXFIFO(MSC_CHN(drive))); /* DMA dest addr */
REG_DMAC_DTCR(DMA_SD_TX_CHANNEL(drive)) = (req->cnt + 3) >> 2; /* DMA transfer count */
REG_DMAC_DRSR(DMA_SD_TX_CHANNEL(drive)) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2OUT : DMAC_DRSR_RS_MSC1OUT; /* DMA request type */
REG_DMAC_DCMD(DMA_SD_TX_CHANNEL) =
REG_DMAC_DCMD(DMA_SD_TX_CHANNEL(drive)) =
#if SD_DMA_INTERRUPT
DMAC_DCMD_TIE | /* Enable DMA interrupt */
#endif
DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 |
DMAC_DCMD_DS_32BIT;
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES;
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(drive)) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES;
/* wait for dma completion */
#if SD_DMA_INTERRUPT
semaphore_wait(&sd_wakeup, TIMEOUT_BLOCK);
semaphore_wait(&sd_wakeup[drive], TIMEOUT_BLOCK);
#else
while (REG_DMAC_DTCR(DMA_SD_TX_CHANNEL))
while (REG_DMAC_DTCR(DMA_SD_TX_CHANNEL(drive)))
yield();
#endif
/* clear status and disable channel */
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) = 0;
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(drive)) = 0;
return SD_NO_ERROR;
}
#if SD_DMA_INTERRUPT
void DMA_CALLBACK(DMA_SD_RX_CHANNEL)(void)
void DMA_CALLBACK(DMA_SD_RX_CHANNEL0)(void)
{
if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) & DMAC_DCCSR_AR)
if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_AR)
{
logf("SD RX DMA address error");
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) &= ~DMAC_DCCSR_AR;
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_AR;
}
if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) & DMAC_DCCSR_HLT)
if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_HLT)
{
logf("SD RX DMA halt");
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) &= ~DMAC_DCCSR_HLT;
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_HLT;
}
if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) & DMAC_DCCSR_TT)
if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_TT)
{
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) &= ~DMAC_DCCSR_TT;
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_TT;
//sd_rx_dma_callback();
}
semaphore_release(&sd_wakeup);
semaphore_release(&sd_wakeup[SD_SLOT_1]);
}
void DMA_CALLBACK(DMA_SD_TX_CHANNEL)(void)
void DMA_CALLBACK(DMA_SD_RX_CHANNEL1)(void)
{
if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) & DMAC_DCCSR_AR)
if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_AR)
{
logf("SD RX DMA address error");
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_AR;
}
if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_HLT)
{
logf("SD RX DMA halt");
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_HLT;
}
if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_TT)
{
REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_TT;
//sd_rx_dma_callback();
}
semaphore_release(&sd_wakeup[SD_SLOT_2]);
}
void DMA_CALLBACK(DMA_SD_TX_CHANNEL0)(void)
{
if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_AR)
{
logf("SD TX DMA address error: %x, %x, %x", var1, var2, var3);
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) &= ~DMAC_DCCSR_AR;
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_AR;
}
if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) & DMAC_DCCSR_HLT)
if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_HLT)
{
logf("SD TX DMA halt");
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) &= ~DMAC_DCCSR_HLT;
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_HLT;
}
if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) & DMAC_DCCSR_TT)
if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_TT)
{
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) &= ~DMAC_DCCSR_TT;
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_TT;
//sd_tx_dma_callback();
}
semaphore_release(&sd_wakeup);
semaphore_release(&sd_wakeup[SD_SLOT_1]);
}
void DMA_CALLBACK(DMA_SD_TX_CHANNEL1)(void)
{
if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_AR)
{
logf("SD TX DMA address error: %x, %x, %x", var1, var2, var3);
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_AR;
}
if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_HLT)
{
logf("SD TX DMA halt");
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_HLT;
}
if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_TT)
{
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_TT;
//sd_tx_dma_callback();
}
semaphore_release(&sd_wakeup[SD_SLOT_2]);
}
#endif /* SD_DMA_INTERRUPT */
#endif /* SD_DMA_ENABLE */
@ -678,7 +736,9 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request)
{
unsigned int cmdat = 0, events = 0;
int retval;
#if !SD_INTERRUPT
long deadline = current_tick + (HZ * 5);
#endif
/* Indicate we have no result yet */
request->result = SD_NO_RESPONSE;
@ -702,8 +762,13 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request)
/* mask all interrupts and clear status */
SD_IRQ_MASK(MSC_CHN(drive));
/*open interrupt */
/* open interrupt */
#if SD_INTERRUPT
REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE);
#else
REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE);
#endif
/* Set command type and events */
switch (request->cmd)
@ -852,15 +917,16 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request)
jz_sd_start_clock(drive);
/* Wait for command completion */
//__intc_unmask_irq(IRQ_MSC);
//semaphore_wait(&sd_wakeup, 100);
#if SD_INTERRUPT
semaphore_wait(&sd_wakeup[drive], HZ * 5);
#else
while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_END_CMD_RES))
{
if (TIME_AFTER(current_tick, deadline))
return SD_ERROR_TIMEOUT;
yield();
}
#endif
REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_END_CMD_RES; /* clear flag */
/* Check for status */
@ -880,41 +946,37 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request)
{
if (events & SD_EVENT_RX_DATA_DONE)
{
#if SD_DMA_ENABLE
retval = jz_sd_receive_data_dma(drive, request);
#else
retval = jz_sd_receive_data(drive, request);
#endif
}
if (retval)
return retval;
if (events & SD_EVENT_TX_DATA_DONE)
{
#if SD_DMA_ENABLE
retval = jz_sd_transmit_data_dma(drive, request);
#else
retval = jz_sd_transmit_data(drive, request);
#endif
}
if (retval)
return retval;
//__intc_unmask_irq(IRQ_MSC);
//semaphore_wait(&sd_wakeup, 100);
#if SD_INTERRUPT
semaphore_wait(&sd_wakeup[drive], HZ * 5);
#else
/* Wait for Data Done */
while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_DATA_TRAN_DONE))
yield();
#endif
REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_DATA_TRAN_DONE; /* clear status */
}
/* Wait for Prog Done event */
if (events & SD_EVENT_PROG_DONE)
{
//__intc_unmask_irq(IRQ_MSC);
//semaphore_wait(&sd_wakeup, 100);
#if SD_INTERRUPT
semaphore_wait(&sd_wakeup[drive], HZ * 5);
#else
while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_PRG_DONE))
yield();
#endif
REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_PRG_DONE; /* clear status */
}
@ -937,7 +999,12 @@ static int jz_sd_chkcard(const int drive)
/* MSC interrupt handler */
void MSC(void)
{
//semaphore_release(&sd_wakeup);
#if SD_INTERRUPT
if (REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) & MSC_IREG_DATA_TRAN_DONE)
semaphore_release(&sd_wakeup[SD_SLOT_1]);
else if (REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) & MSC_IREG_DATA_TRAN_DONE)
semaphore_release(&sd_wakeup[SD_SLOT_2]);
#endif
logf("MSC interrupt");
}
@ -1188,20 +1255,19 @@ static int sd_select_card(const int drive)
return 0;
}
static int sd_init_device(const int drive)
static int __sd_init_device(const int drive)
{
int retval = 0;
long deadline;
struct sd_request init_req;
mutex_lock(&sd_mtx);
/* Initialise card data as blank */
memset(&card[drive], 0, sizeof(tCardInfo));
sd2_0[drive] = 0;
num_6[drive] = 0;
use_4bit[drive] = 0;
active[drive] = 0;
/* reset mmc/sd controller */
jz_sd_hardware_init(drive);
@ -1223,8 +1289,6 @@ static int sd_init_device(const int drive)
else
__cpm_stop_msc1(); /* disable SD2 clock */
mutex_unlock(&sd_mtx);
return retval;
}
@ -1235,28 +1299,37 @@ int sd_init(void)
sd_init_gpio(); /* init GPIO */
#if SD_DMA_ENABLE
__dmac_channel_enable_clk(DMA_SD_RX_CHANNEL);
__dmac_channel_enable_clk(DMA_SD_TX_CHANNEL);
__dmac_channel_enable_clk(DMA_SD_RX_CHANNEL(SD_SLOT_1));
__dmac_channel_enable_clk(DMA_SD_RX_CHANNEL(SD_SLOT_2));
__dmac_channel_enable_clk(DMA_SD_TX_CHANNEL(SD_SLOT_1));
__dmac_channel_enable_clk(DMA_SD_TX_CHANNEL(SD_SLOT_2));
#endif
if(!inited)
{
#if SD_DMA_INTERRUPT
semaphore_init(&sd_wakeup, 1, 0);
#if SD_DMA_INTERRUPT || SD_INTERRUPT
semaphore_init(&sd_wakeup[SD_SLOT_1], 1, 0);
semaphore_init(&sd_wakeup[SD_SLOT_2], 1, 0);
#endif
mutex_init(&sd_mtx);
mutex_init(&sd_mtx[SD_SLOT_1]);
mutex_init(&sd_mtx[SD_SLOT_2]);
#if SD_DMA_ENABLE && SD_DMA_INTERRUPT
system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL));
system_enable_irq(DMA_IRQ(DMA_SD_TX_CHANNEL));
system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL(SD_SLOT_1)));
system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL(SD_SLOT_2)));
system_enable_irq(DMA_IRQ(DMA_SD_TX_CHANNEL(SD_SLOT_1)));
system_enable_irq(DMA_IRQ(DMA_SD_TX_CHANNEL(SD_SLOT_2)));
#endif
inited = true;
}
for (int drive = 0; drive < NUM_DRIVES; drive++)
sd_init_device(drive);
for (int drive = 0; drive < NUM_DRIVES; drive++) {
mutex_lock(&sd_mtx[drive]);
__sd_init_device(drive);
mutex_unlock(&sd_mtx[drive]);
}
return 0;
}
@ -1273,22 +1346,26 @@ tCardInfo* card_get_info_target(const int drive)
static inline void sd_start_transfer(const int drive)
{
mutex_lock(&sd_mtx);
mutex_lock(&sd_mtx[drive]);
if (drive == SD_SLOT_1)
__cpm_start_msc2();
else
__cpm_start_msc1();
led(true);
active[drive] = 1;
led(active[SD_SLOT_1] || active[SD_SLOT_2]);
}
static inline void sd_stop_transfer(const int drive)
{
led(false);
active[drive] = 0;
led(active[SD_SLOT_1] || active[SD_SLOT_2]);
if (drive == SD_SLOT_1)
__cpm_stop_msc2();
else
__cpm_stop_msc1();
mutex_unlock(&sd_mtx);
mutex_unlock(&sd_mtx[drive]);
}
int sd_transfer_sectors(IF_MD(const int drive,) unsigned long start, int count, void* buf, bool write)
@ -1305,7 +1382,7 @@ int sd_transfer_sectors(IF_MD(const int drive,) unsigned long start, int count,
if (!card_detect_target(drive) || count < 1 || (start + count) > card[drive].numblocks)
goto err;
if(card[drive].initialized == 0 && !sd_init_device(drive))
if(card[drive].initialized == 0 && !__sd_init_device(drive))
goto err;
sd_simple_cmd(drive, &request, SD_SEND_STATUS, card[drive].rca, RESPONSE_R1);
@ -1440,11 +1517,11 @@ int sd_event(long id, intptr_t data)
case SYS_HOTSWAP_EXTRACTED:
/* Force card init for new card, re-init for re-inserted one or
* clear if the last attempt to init failed with an error. */
mutex_lock(&sd_mtx); /* lock-out card activity */
mutex_lock(&sd_mtx[data]); /* lock-out card activity */
card[data].initialized = 0;
if (id == SYS_HOTSWAP_INSERTED)
sd_init_device(data);
mutex_unlock(&sd_mtx);
__sd_init_device(data);
mutex_unlock(&sd_mtx[data]);
break;
#endif /* HAVE_HOTSWAP */
default:

View file

@ -664,8 +664,10 @@ void dma_preinit(void)
REG_MDMAC_DMACKES = 0x1;
REG_DMAC_DMACR(DMA_AIC_TX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FAIC;
REG_DMAC_DMACR(DMA_SD_RX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC;
REG_DMAC_DMACR(DMA_SD_TX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC;
REG_DMAC_DMACR(DMA_SD_RX_CHANNEL(0)) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC;
REG_DMAC_DMACR(DMA_SD_RX_CHANNEL(1)) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC;
REG_DMAC_DMACR(DMA_SD_TX_CHANNEL(0)) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC;
REG_DMAC_DMACR(DMA_SD_TX_CHANNEL(1)) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC;
}
/* Gets called *before* main */

View file

@ -97,8 +97,13 @@ void dma_disable(void);
#define DMA_AIC_TX_CHANNEL 0
#define DMA_NAND_CHANNEL 1
#define DMA_USB_CHANNEL 2
#define DMA_SD_RX_CHANNEL 3
#define DMA_SD_TX_CHANNEL 4
#define DMA_SD_RX_CHANNEL0 3
#define DMA_SD_RX_CHANNEL1 4
// Note: channel 5 and 11 cannot be used!
#define DMA_SD_TX_CHANNEL0 6
#define DMA_SD_TX_CHANNEL1 7
#define DMA_SD_RX_CHANNEL(n) 3+n
#define DMA_SD_TX_CHANNEL(n) 6+n
#endif
#define XDMA_CALLBACK(n) DMA ## n