Commit b0a1bdcd authored by Tony Lindgren's avatar Tony Lindgren

musb_hdrc: Transfer remaining bytes with PIO

DMA callback can manually transfer remaining 1 - 31 bytes
after DMA transfer using PIO. This allows transferring
a wider range of sizes with DMA.

This needs to be tested with sync DMA transfers as
PIO may not be mixed with sync DMA.
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 9c97d4aa
...@@ -146,7 +146,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) ...@@ -146,7 +146,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
struct musb_hw_ep *hw_ep = chdat->hw_ep; struct musb_hw_ep *hw_ep = chdat->hw_ep;
void __iomem *ep_conf = hw_ep->conf; void __iomem *ep_conf = hw_ep->conf;
void __iomem *musb_base = musb->pRegs; void __iomem *musb_base = musb->pRegs;
unsigned long remaining, flags; unsigned long remaining, flags, pio;
int ch; int ch;
spin_lock_irqsave(&musb->Lock, flags); spin_lock_irqsave(&musb->Lock, flags);
...@@ -170,21 +170,25 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) ...@@ -170,21 +170,25 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining); remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining);
channel->dwActualLength = chdat->transfer_len - remaining; channel->dwActualLength = chdat->transfer_len - remaining;
pio = chdat->len - channel->dwActualLength;
DBG(2, "DMA remaining %lu/%u\n", remaining, chdat->transfer_len); DBG(2, "DMA remaining %lu/%u\n", remaining, chdat->transfer_len);
/* Transfer remaining 1 - 31 bytes if DMA worked */ /* Transfer remaining 1 - 31 bytes */
if (remaining == 0) { if (pio > 0 && pio < 32) {
u32 pio;
u8 *buf; u8 *buf;
pio = chdat->len - channel->dwActualLength; DBG(2, "Using PIO for remaining %i bytes\n", pio);
buf = phys_to_virt((u32)chdat->dma_addr) buf = phys_to_virt((u32)chdat->dma_addr) + chdat->transfer_len;
+ chdat->transfer_len; if (chdat->tx) {
if (chdat->tx) consistent_sync(phys_to_virt((u32)chdat->dma_addr),
chdat->transfer_len, DMA_TO_DEVICE);
musb_write_fifo(hw_ep, pio, buf); musb_write_fifo(hw_ep, pio, buf);
else } else {
musb_read_fifo(hw_ep, pio, buf); musb_read_fifo(hw_ep, pio, buf);
consistent_sync(phys_to_virt((u32)chdat->dma_addr),
chdat->transfer_len, DMA_FROM_DEVICE);
}
channel->dwActualLength += pio; channel->dwActualLength += pio;
} }
...@@ -201,7 +205,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) ...@@ -201,7 +205,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
if (!chdat->tx) if (!chdat->tx)
musb_dma_completion(musb, chdat->epnum, chdat->tx); musb_dma_completion(musb, chdat->epnum, chdat->tx);
/* We musb terminate short tx transfers manually by setting TXPKTRDY. /* We must terminate short tx transfers manually by setting TXPKTRDY.
* REVISIT: This same problem may occur with other MUSB dma as well. * REVISIT: This same problem may occur with other MUSB dma as well.
* Easy to test with g_ether by pinging the MUSB board with ping -s54. * Easy to test with g_ether by pinging the MUSB board with ping -s54.
*/ */
...@@ -239,7 +243,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, ...@@ -239,7 +243,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
s8 dmareq; s8 dmareq;
s8 sync_dev; s8 sync_dev;
if (unlikely(dma_addr & 0x1) || len < 32) if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return FALSE; return FALSE;
chdat->transfer_len = len & ~0x1f; chdat->transfer_len = len & ~0x1f;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment