From: Bryan Wu <cooloney@xxxxxxxxxx> - MUSB_POLL_DMA option use DMA polling method to do FIFO read/write when we usb PIO mode. Adding this because pure PIO mode is no very stable during the USB testing - Add ANOMALY_05000380 handling for BF527 (< 0.2 silicon) Signed-off-by: Bryan Wu <cooloney@xxxxxxxxxx> Signed-off-by: Mike Frysinger <vapier@xxxxxxxxxx> --- drivers/usb/musb/Kconfig | 8 ++++++++ drivers/usb/musb/blackfin.c | 42 +++++++++++++++++++++++++++++++++++++++++- drivers/usb/musb/blackfin.h | 2 +- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index b66e854..afd8289 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -148,6 +148,14 @@ config MUSB_PIO_ONLY you can still disable it at run time using the "use_dma=n" module parameter. +config MUSB_DMA_POLL + bool 'Using DMA polling in MUSB PIO mode' + depends on MUSB_PIO_ONLY && BLACKFIN + default y if BLACKFIN + help + Using DMA busy loop polling to copy to/from FIFO. Because pure + PIO mode sometimes is also unstable in our testing. + config USB_INVENTRA_DMA bool depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 817afc5..2b42864 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -30,6 +30,10 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) { void __iomem *fifo = hw_ep->fifo; void __iomem *epio = hw_ep->regs; +#if defined(CONFIG_MUSB_DMA_POLL) && (!ANOMALY_05000380) + u8 epnum = hw_ep->epnum; + u16 dma_reg = 0; +#endif prefetch((u8 *)src); @@ -40,12 +44,48 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) dump_fifo_data(src, len); +#if defined(CONFIG_MUSB_DMA_POLL) && (!ANOMALY_05000380) + flush_dcache_range((unsigned int)src, + (unsigned int)(src + len)); + + /* Setup DMA address register */ + dma_reg = (u16) ((u32) src & 0xFFFF); + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); + SSYNC(); + + dma_reg = (u16) (((u32) src >> 16) & 0xFFFF); + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); + SSYNC(); + + /* Setup DMA count register */ + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); + SSYNC(); + + /* Enable the DMA */ + dma_reg = (epnum << 4) | DMA_ENA | INT_ENA | DIRECTION; + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); + SSYNC(); + + /* Wait for compelete */ + while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) + cpu_relax(); + + /* acknowledge dma interrupt */ + bfin_write_USB_DMA_INTERRUPT(1 << epnum); + SSYNC(); + + /* Reset DMA */ + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); + SSYNC(); +#else if (unlikely((unsigned long)src & 0x01)) outsw_8((unsigned long)fifo, src, len & 0x01 ? (len >> 1) + 1 : len >> 1); else outsw((unsigned long)fifo, src, len & 0x01 ? (len >> 1) + 1 : len >> 1); +#endif } /* @@ -55,7 +95,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) { void __iomem *fifo = hw_ep->fifo; -#ifdef CONFIG_BF52x +#if defined(CONFIG_MUSB_DMA_POLL) u8 epnum = hw_ep->epnum; u16 dma_reg = 0; diff --git a/drivers/usb/musb/blackfin.h b/drivers/usb/musb/blackfin.h index a240c1e..159fdea 100644 --- a/drivers/usb/musb/blackfin.h +++ b/drivers/usb/musb/blackfin.h @@ -32,7 +32,7 @@ static void dump_fifo_data(u8 *buf, u16 len) #define dump_fifo_data(buf, len) do {} while (0) #endif -#ifdef CONFIG_BF52x +#if defined(CONFIG_MUSB_DMA_POLL) #define USB_DMA_BASE USB_DMA_INTERRUPT #define USB_DMAx_CTRL 0x04 -- 1.6.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html