From 63ef81de314a29b3289ff896a29a8844c6f1607f Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Mon, 24 Aug 2020 23:34:34 -0400 Subject: 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 --- .../target/mips/ingenic_jz47xx/ata-sd-jz4760.c | 251 ++++++++++++++------- .../target/mips/ingenic_jz47xx/system-jz4760.c | 6 +- .../target/mips/ingenic_jz47xx/system-target.h | 9 +- 3 files changed, 175 insertions(+), 91 deletions(-) diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c index 6862262045..0717f80b9d 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c @@ -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: diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4760.c b/firmware/target/mips/ingenic_jz47xx/system-jz4760.c index 3d4015c465..eb20985b97 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4760.c @@ -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 */ diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h index 9720d3a80c..b6e779ea53 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-target.h +++ b/firmware/target/mips/ingenic_jz47xx/system-target.h @@ -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 -- cgit v1.2.3