Blackfin arch: DMA operation cleanup
1) Disable Interrupts during DMA memcpy to avoid raise conditions. 2) Mark MDMA channel 0 as reserved, since were using it internally. 3) Add DMA based equivalents for insX and outsX. 4) Our insX and outsX only handles len <= 2^16. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
d1b945fdb6
Коммит
23ee968d96
|
@ -130,7 +130,9 @@ static int __init blackfin_dma_init(void)
|
|||
dma_ch[i].regs = base_addr[i];
|
||||
mutex_init(&(dma_ch[i].dmalock));
|
||||
}
|
||||
|
||||
/* Mark MEMDMA Channel 0 as requested since we're using it internally */
|
||||
dma_ch[CH_MEM_STREAM0_DEST].chan_status = DMA_CHANNEL_REQUESTED;
|
||||
dma_ch[CH_MEM_STREAM0_SRC].chan_status = DMA_CHANNEL_REQUESTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -598,9 +600,12 @@ void *dma_memcpy(void *dest, const void *src, size_t size)
|
|||
int direction; /* 1 - address decrease, 0 - address increase */
|
||||
int flag_align; /* 1 - address aligned, 0 - address unaligned */
|
||||
int flag_2D; /* 1 - 2D DMA needed, 0 - 1D DMA needed */
|
||||
unsigned long flags;
|
||||
|
||||
if (size <= 0)
|
||||
return NULL;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if ((unsigned long)src < memory_end)
|
||||
blackfin_dcache_flush_range((unsigned int)src,
|
||||
|
@ -725,6 +730,7 @@ void *dma_memcpy(void *dest, const void *src, size_t size)
|
|||
if ((unsigned long)dest < memory_end)
|
||||
blackfin_dcache_invalidate_range((unsigned int)dest,
|
||||
(unsigned int)(dest + size));
|
||||
local_irq_restore(flags);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
@ -732,11 +738,201 @@ EXPORT_SYMBOL(dma_memcpy);
|
|||
|
||||
void *safe_dma_memcpy(void *dest, const void *src, size_t size)
|
||||
{
|
||||
int flags = 0;
|
||||
void *addr;
|
||||
local_irq_save(flags);
|
||||
addr = dma_memcpy(dest, src, size);
|
||||
local_irq_restore(flags);
|
||||
return addr;
|
||||
}
|
||||
EXPORT_SYMBOL(safe_dma_memcpy);
|
||||
|
||||
void dma_outsb(void __iomem *addr, const void *buf, unsigned short len)
|
||||
{
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
|
||||
|
||||
bfin_write_MDMA_D0_START_ADDR(addr);
|
||||
bfin_write_MDMA_D0_X_COUNT(len);
|
||||
bfin_write_MDMA_D0_X_MODIFY(0);
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_START_ADDR(buf);
|
||||
bfin_write_MDMA_S0_X_COUNT(len);
|
||||
bfin_write_MDMA_S0_X_MODIFY(1);
|
||||
bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
|
||||
bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
|
||||
|
||||
while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
|
||||
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(0);
|
||||
bfin_write_MDMA_D0_CONFIG(0);
|
||||
local_irq_restore(flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(dma_outsb);
|
||||
|
||||
|
||||
void dma_insb(const void __iomem *addr, void *buf, unsigned short len)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
bfin_write_MDMA_D0_START_ADDR(buf);
|
||||
bfin_write_MDMA_D0_X_COUNT(len);
|
||||
bfin_write_MDMA_D0_X_MODIFY(1);
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_START_ADDR(addr);
|
||||
bfin_write_MDMA_S0_X_COUNT(len);
|
||||
bfin_write_MDMA_S0_X_MODIFY(0);
|
||||
bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
|
||||
bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
|
||||
|
||||
blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len);
|
||||
|
||||
while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
|
||||
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(0);
|
||||
bfin_write_MDMA_D0_CONFIG(0);
|
||||
local_irq_restore(flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(dma_insb);
|
||||
|
||||
void dma_outsw(void __iomem *addr, const void *buf, unsigned short len)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
|
||||
|
||||
bfin_write_MDMA_D0_START_ADDR(addr);
|
||||
bfin_write_MDMA_D0_X_COUNT(len);
|
||||
bfin_write_MDMA_D0_X_MODIFY(0);
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_START_ADDR(buf);
|
||||
bfin_write_MDMA_S0_X_COUNT(len);
|
||||
bfin_write_MDMA_S0_X_MODIFY(2);
|
||||
bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
|
||||
bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
|
||||
|
||||
while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
|
||||
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(0);
|
||||
bfin_write_MDMA_D0_CONFIG(0);
|
||||
local_irq_restore(flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(dma_outsw);
|
||||
|
||||
void dma_insw(const void __iomem *addr, void *buf, unsigned short len)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
bfin_write_MDMA_D0_START_ADDR(buf);
|
||||
bfin_write_MDMA_D0_X_COUNT(len);
|
||||
bfin_write_MDMA_D0_X_MODIFY(2);
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_START_ADDR(addr);
|
||||
bfin_write_MDMA_S0_X_COUNT(len);
|
||||
bfin_write_MDMA_S0_X_MODIFY(0);
|
||||
bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
|
||||
bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
|
||||
|
||||
blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len);
|
||||
|
||||
while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
|
||||
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(0);
|
||||
bfin_write_MDMA_D0_CONFIG(0);
|
||||
local_irq_restore(flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(dma_insw);
|
||||
|
||||
void dma_outsl(void __iomem *addr, const void *buf, unsigned short len)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
|
||||
|
||||
bfin_write_MDMA_D0_START_ADDR(addr);
|
||||
bfin_write_MDMA_D0_X_COUNT(len);
|
||||
bfin_write_MDMA_D0_X_MODIFY(0);
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_START_ADDR(buf);
|
||||
bfin_write_MDMA_S0_X_COUNT(len);
|
||||
bfin_write_MDMA_S0_X_MODIFY(4);
|
||||
bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
|
||||
bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
|
||||
|
||||
while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
|
||||
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(0);
|
||||
bfin_write_MDMA_D0_CONFIG(0);
|
||||
local_irq_restore(flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(dma_outsl);
|
||||
|
||||
void dma_insl(const void __iomem *addr, void *buf, unsigned short len)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
bfin_write_MDMA_D0_START_ADDR(buf);
|
||||
bfin_write_MDMA_D0_X_COUNT(len);
|
||||
bfin_write_MDMA_D0_X_MODIFY(4);
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_START_ADDR(addr);
|
||||
bfin_write_MDMA_S0_X_COUNT(len);
|
||||
bfin_write_MDMA_S0_X_MODIFY(0);
|
||||
bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
|
||||
bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
|
||||
|
||||
blackfin_dcache_invalidate_range((unsigned int)buf, (unsigned int)(buf) + len);
|
||||
|
||||
while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
|
||||
|
||||
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
|
||||
|
||||
bfin_write_MDMA_S0_CONFIG(0);
|
||||
bfin_write_MDMA_D0_CONFIG(0);
|
||||
local_irq_restore(flags);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(dma_insl);
|
||||
|
|
|
@ -115,13 +115,21 @@ static inline unsigned int readl(void __iomem *addr)
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
extern void outsb(void __iomem *port, const void *addr, unsigned long count);
|
||||
extern void outsw(void __iomem *port, const void *addr, unsigned long count);
|
||||
extern void outsl(void __iomem *port, const void *addr, unsigned long count);
|
||||
extern void outsb(void __iomem *port, const void *addr, unsigned short count);
|
||||
extern void outsw(void __iomem *port, const void *addr, unsigned short count);
|
||||
extern void outsl(void __iomem *port, const void *addr, unsigned short count);
|
||||
|
||||
extern void insb(const void __iomem *port, void *addr, unsigned long count);
|
||||
extern void insw(const void __iomem *port, void *addr, unsigned long count);
|
||||
extern void insl(const void __iomem *port, void *addr, unsigned long count);
|
||||
extern void insb(const void __iomem *port, void *addr, unsigned short count);
|
||||
extern void insw(const void __iomem *port, void *addr, unsigned short count);
|
||||
extern void insl(const void __iomem *port, void *addr, unsigned short count);
|
||||
|
||||
extern void dma_outsb(void __iomem *port, const void *addr, unsigned short count);
|
||||
extern void dma_outsw(void __iomem *port, const void *addr, unsigned short count);
|
||||
extern void dma_outsl(void __iomem *port, const void *addr, unsigned short count);
|
||||
|
||||
extern void dma_insb(const void __iomem *port, void *addr, unsigned short count);
|
||||
extern void dma_insw(const void __iomem *port, void *addr, unsigned short count);
|
||||
extern void dma_insl(const void __iomem *port, void *addr, unsigned short count);
|
||||
|
||||
/*
|
||||
* Map some physical address range into the kernel address space.
|
||||
|
|
Загрузка…
Ссылка в новой задаче