mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 08:19:28 +00:00
Blackfin: fix early_dma_memcpy() handling of busy channels
The early logic to locate a free DMA channel and then set it up was broken in a few ways that only manifested itself when we needed to set up more than 2 on chip SRAM regions (most board defaults setup 1 or 2). First, we checked the wrong status register (the destination gets updated, not the source) and second, we did the ssync before rather than after resetting a DMA config register. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
parent
fb4b5d3a37
commit
532f07ca04
1 changed files with 19 additions and 20 deletions
|
@ -253,32 +253,31 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
|
|||
BUG_ON(src % 4);
|
||||
BUG_ON(size % 4);
|
||||
|
||||
src_ch = 0;
|
||||
/* Find an avalible memDMA channel */
|
||||
while (1) {
|
||||
if (src_ch == (struct dma_register *)MDMA_S0_NEXT_DESC_PTR) {
|
||||
dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR;
|
||||
src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR;
|
||||
} else {
|
||||
dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR;
|
||||
src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR;
|
||||
}
|
||||
|
||||
if (!bfin_read16(&src_ch->cfg))
|
||||
break;
|
||||
else if (bfin_read16(&dst_ch->irq_status) & DMA_DONE) {
|
||||
bfin_write16(&src_ch->cfg, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Force a sync in case a previous config reset on this channel
|
||||
* occurred. This is needed so subsequent writes to DMA registers
|
||||
* are not spuriously lost/corrupted.
|
||||
*/
|
||||
__builtin_bfin_ssync();
|
||||
|
||||
src_ch = 0;
|
||||
/* Find an avalible memDMA channel */
|
||||
while (1) {
|
||||
if (!src_ch || src_ch == (struct dma_register *)MDMA_S1_NEXT_DESC_PTR) {
|
||||
dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR;
|
||||
src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR;
|
||||
} else {
|
||||
dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR;
|
||||
src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR;
|
||||
}
|
||||
|
||||
if (!bfin_read16(&src_ch->cfg)) {
|
||||
break;
|
||||
} else {
|
||||
if (bfin_read16(&src_ch->irq_status) & DMA_DONE)
|
||||
bfin_write16(&src_ch->cfg, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Destination */
|
||||
bfin_write32(&dst_ch->start_addr, dst);
|
||||
bfin_write16(&dst_ch->x_count, size >> 2);
|
||||
|
|
Loading…
Reference in a new issue