From d4af81c7e93e3de24174a1839dc6fd9ab8082b50 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 30 Apr 2007 19:04:26 +0000 Subject: [PATCH] musb_hdrc: DMA RX workaround for tusb6010 Async RX DMA on tusb6010 will eventually corrupt the XFR_SIZE register. This patch blocks DMA transfers for async RX DMA. Signed-off-by: Tony Lindgren --- drivers/usb/musb/tusb6010_omap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index 1d9d80f374c..1ca6a3a1fa2 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -169,6 +169,13 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET); remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining); + + /* HW issue #10: XFR_SIZE may get corrupt on async DMA */ + if (unlikely(remaining > chdat->transfer_len)) { + WARN("Corrupt XFR_SIZE with async DMA: %lu\n", remaining); + remaining = 0; + } + channel->dwActualLength = chdat->transfer_len - remaining; pio = chdat->len - channel->dwActualLength; @@ -246,6 +253,15 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz)) return FALSE; + /* + * HW issue #10: Async dma will eventually corrupt the XFR_SIZE + * register which will cause missed DMA interrupt. We could try to + * use a timer for the callback, but it is unsafe as the XFR_SIZE + * register is corrupt, and we won't know if the DMA worked. + */ + if (dma_addr & 0x2) + return FALSE; + chdat->transfer_len = len & ~0x1f; if (len < packet_sz) -- 2.41.1