mips: Heavily rework DMA & caching code

Based on code originally written by Amaury Pouly (g#1789, g#1791, g#1527)
but rebased and heavily updated.

Change-Id: Ic794abb5e8d89feb4b88fc3abe854270fb28db70
This commit is contained in:
Solomon Peachy 2020-08-28 21:45:58 -04:00
parent 1ae8213a64
commit 0cb162a76b
16 changed files with 188 additions and 129 deletions

View file

@ -151,7 +151,7 @@ static void jz_nand_write_dma(void *source, unsigned int len, int bw)
mutex_lock(&nand_dma_mtx);
if(((unsigned int)source < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)source, len);
commit_discard_dcache_range(source, len);
dma_enable();
@ -184,7 +184,7 @@ static void jz_nand_read_dma(void *target, unsigned int len, int bw)
mutex_lock(&nand_dma_mtx);
if(((unsigned int)target < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)target, len);
discard_dcache_range(target, len);
dma_enable();

View file

@ -150,7 +150,7 @@ static void jz_nand_write_dma(void *source, unsigned int len, int bw)
mutex_lock(&nand_dma_mtx);
if(((unsigned int)source < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)source, len);
commit_discard_dcache_range(source, len);
dma_enable();
@ -183,7 +183,7 @@ static void jz_nand_read_dma(void *target, unsigned int len, int bw)
mutex_lock(&nand_dma_mtx);
if(((unsigned int)target < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)target, len);
discard_dcache_range(target, len);
dma_enable();

View file

@ -417,7 +417,7 @@ static void jz_sd_receive_data_dma(struct sd_request *req)
#endif
/* flush dcache */
//dma_cache_wback_inv((unsigned long) req->buffer, size);
discard_dcache_range(req->buffer, size);
/* setup dma channel */
REG_DMAC_DSAR(DMA_SD_RX_CHANNEL) = PHYSADDR(MSC_RXFIFO); /* DMA source addr */
REG_DMAC_DTAR(DMA_SD_RX_CHANNEL) = PHYSADDR((unsigned long) req->buffer); /* DMA dest addr */
@ -452,7 +452,7 @@ static void jz_mmc_transmit_data_dma(struct mmc_request *req)
#endif
/* flush dcache */
//dma_cache_wback_inv((unsigned long) req->buffer, size);
commit_discard_dcache_range(req->buffer, size);
/* setup dma channel */
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); /* DMA dest addr */

View file

@ -532,6 +532,9 @@ 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)
{
/* flush dcache */
discard_dcache_range(req->buffer, req->cnt);
/* setup dma channel */
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 */
@ -558,16 +561,13 @@ static int jz_sd_receive_data_dma(const int drive, struct sd_request *req)
/* clear status and disable channel */
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)
{
/* flush dcache */
dma_cache_wback_inv((unsigned long) req->buffer, req->cnt);
commit_discard_dcache_range(req->buffer, req->cnt);
/* setup dma channel */
REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(drive)) = 0;

View file

@ -32,7 +32,7 @@ void memset(void *target, unsigned char c, size_t len)
else
{
if(((unsigned int)target < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)target, len);
discard_dcache_range(target, len);
dp = (unsigned char *)((unsigned int)(&d) | 0xa0000000);
*(dp + 0) = c;
@ -52,7 +52,6 @@ void memset(void *target, unsigned char c, size_t len)
dp = (unsigned char *)((unsigned int)target + (len & (32 - 1)));
for(d = 0;d < (len % 32); d++)
*dp++ = c;
}
}
}
@ -68,7 +67,7 @@ void memset16(void *target, unsigned short c, size_t len)
else
{
if(((unsigned int)target < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)target, len);
discard_dcache_range(target, len);
d = c;
REG_DMAC_DSAR(ch) = PHYSADDR((unsigned long)&d);
@ -97,10 +96,10 @@ void memcpy(void *target, const void *source, size_t len)
_memcpy(target, source, len);
if(((unsigned int)source < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)source, len);
commit_dcache_range(source, len);
if(((unsigned int)target < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)target, len);
discard_dcache_range(target, len);
REG_DMAC_DSAR(ch) = PHYSADDR((unsigned long)source);
REG_DMAC_DTAR(ch) = PHYSADDR((unsigned long)target);

View file

@ -29,7 +29,7 @@ void memset_dma(void *target, int c, size_t len, unsigned int bits)
unsigned char *dp;
if(((unsigned int)target < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)target, len);
discard_dcache_range(target, len);
dp = (unsigned char *)((unsigned int)(&d) | 0xa0000000);
*(dp + 0) = c;
@ -68,14 +68,14 @@ void memset_dma(void *target, int c, size_t len, unsigned int bits)
void memcpy_dma(void *target, const void *source, size_t len, unsigned int bits)
{
if(((unsigned int)source < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)source, len);
commit_dcache_range(source, len);
if(((unsigned int)target < 0xa0000000) && len)
dma_cache_wback_inv((unsigned long)target, len);
discard_dcache_range(target, len);
REG_MDMAC_DCCSR(MDMA_CHANNEL) = 0;
REG_MDMAC_DSAR(MDMA_CHANNEL) = PHYSADDR((unsigned long)source);
REG_MDMAC_DTAR(MDMA_CHANNEL) = PHYSADDR((unsigned long)target);
REG_MDMAC_DTAR(MDMA_CHANNEL) = PHYSADDR((unsigned long)target);
REG_MDMAC_DRSR(MDMA_CHANNEL) = DMAC_DRSR_RS_AUTO;
switch (bits)
{

View file

@ -109,8 +109,9 @@ void lcd_update_rect(int x, int y, int width, int height)
REG_DMAC_DCMD(DMA_LCD_CHANNEL) = ( DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32
| DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BYTE );
__dcache_writeback_all(); /* Size of framebuffer is way bigger than cache size.
We need to find a way to make the framebuffer uncached, so this statement can get removed. */
// XXX range
commit_discard_dcache(); /* Size of framebuffer is way bigger than cache size.
We need to find a way to make the framebuffer uncached, so this statement can get removed. */
while(REG_SLCD_STATE & SLCD_STATE_BUSY);
REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; /* Enable SLCD DMA support */
@ -174,7 +175,7 @@ void lcd_blit_yuv(unsigned char * const src[3],
yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
__dcache_writeback_all();
commit_discard_dcache(); // XXX range
__cpm_start_ipu();

View file

@ -69,6 +69,8 @@ static inline void set_dma(const void *addr, size_t size)
int burst_size;
logf("%x %d %x", (unsigned int)addr, size, REG_AIC_SR);
commit_discard_dcache_range(addr, size);
if(size % 16)
{
if(size % 4)
@ -88,7 +90,6 @@ static inline void set_dma(const void *addr, size_t size)
burst_size = DMAC_DCMD_DS_16BYTE;
}
__dcache_writeback_all();
REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = DMAC_DCCSR_NDES;
REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)addr);
REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)AIC_DR);

View file

@ -28,7 +28,6 @@
#include "pcm-internal.h"
#include "cpu.h"
/****************************************************************************
** Playback DMA transfer
**/
@ -60,8 +59,8 @@ static inline void set_dma(const void *addr, size_t size)
int burst_size;
logf("%x %d %x", (unsigned int)addr, size, REG_AIC_SR);
dma_cache_wback_inv((unsigned long)addr, size);
commit_discard_dcache_range(addr, size);
if(size % 16)
{
if(size % 4)

View file

@ -511,24 +511,23 @@ static void sdram_init(void)
void ICODE_ATTR system_main(void)
{
int i;
__dcache_writeback_all();
__icache_invalidate_all();
commit_discard_idcache();
write_c0_status(1 << 28 | 1 << 10 ); /* Enable CP | Mask interrupt 2 */
/* Disable all interrupts */
for(i=0; i<IRQ_MAX; i++)
dis_irq(i);
mmu_init();
pll_init();
sdram_init();
/* Disable unneeded clocks, clocks are enabled when needed */
__cpm_stop_all();
__cpm_suspend_usbhost();
/* Enable interrupts at core level */
enable_interrupt();
}

View file

@ -673,8 +673,7 @@ void ICODE_ATTR system_main(void)
{
int i;
__dcache_writeback_all();
__icache_invalidate_all();
commit_discard_idcache();
write_c0_status(1 << 28 | 1 << 10 ); /* Enable CP | Mask interrupt 2 */

View file

@ -274,7 +274,7 @@ static void EPIN_handler(unsigned int endpoint)
}
logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length);
if(ep->sent == 0)
length = MIN(ep->length, ep->fifo_size);
else
@ -365,7 +365,7 @@ static void EPDMA_handler(int number)
/* Disable DMA */
REG_USB_REG_CNTL2 = 0;
__dcache_invalidate_all();
commit_discard_dcache(); // XXX range?
select_endpoint(endpoint);
/* Read out last packet manually */
@ -707,8 +707,7 @@ static void usb_drv_send_internal(struct usb_endpoint* ep, void* ptr, int length
{
if(ep->use_dma)
{
//dma_cache_wback_inv((unsigned long)ptr, length);
__dcache_writeback_all();
commit_discard_dcache_range(ptr, length);
REG_USB_REG_ADDR1 = PHYSADDR((unsigned long)ptr);
REG_USB_REG_COUNT1 = length;
REG_USB_REG_CNTL1 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 |
@ -767,8 +766,7 @@ int usb_drv_recv(int endpoint, void* ptr, int length)
ep->busy = true;
if(ep->use_dma)
{
//dma_cache_wback_inv((unsigned long)ptr, length);
__dcache_writeback_all();
discard_dcache_range(ptr, length);
REG_USB_REG_ADDR2 = PHYSADDR((unsigned long)ptr);
REG_USB_REG_COUNT2 = length;
REG_USB_REG_CNTL2 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 |

View file

@ -360,7 +360,7 @@ static void EPIN_handler(unsigned int endpoint)
}
logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length);
if(ep->sent == 0)
length = MIN(ep->length, ep->fifo_size);
else
@ -456,7 +456,7 @@ static void EPDMA_handler(int number)
/* Disable DMA */
REG_USB_CNTL(1) = 0;
__dcache_invalidate_all();
commit_discard_dcache(); // XXX range?
select_endpoint(endpoint);
/* Read out last packet manually */
@ -846,8 +846,7 @@ static void usb_drv_send_internal(struct usb_endpoint* ep, void* ptr, int length
{
if(ep->use_dma)
{
//dma_cache_wback_inv((unsigned long)ptr, length);
__dcache_writeback_all();
commit_discard_dcache_range(ptr, length);
REG_USB_ADDR(0) = PHYSADDR((unsigned long)ptr);
REG_USB_COUNT(0) = length;
REG_USB_CNTL(0) = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 |
@ -921,8 +920,7 @@ int usb_drv_recv(int endpoint, void* ptr, int length)
ep->busy = true;
if(ep->use_dma)
{
//dma_cache_wback_inv((unsigned long)ptr, length);
__dcache_writeback_all();
discard_dcache_range(ptr, length);
REG_USB_ADDR(1) = PHYSADDR((unsigned long)ptr);
REG_USB_COUNT(1) = length;
REG_USB_CNTL(1) = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 |