USB: musb: workaround Blackfin FIFO anomalies

Some of these workarounds are already in place, but labeled as affecting
all BF52x parts.  Since we have official anomaly numbers now, use those
defines.  And since writing to the FIFO has a similar hang issue as reading
from the FIFO, implement the workaround there too when necessary.

Signed-off-by: Bryan Wu <cooloney@kernel.org>
Signed-off-by: Cliff Cai <cliff.cai@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Cc: Felipe Balbi <felipe.balbi@nokia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index fe4934d..ad26e65 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -29,6 +29,8 @@
 {
 	void __iomem *fifo = hw_ep->fifo;
 	void __iomem *epio = hw_ep->regs;
+	u8 epnum = hw_ep->epnum;
+	u16 dma_reg = 0;
 
 	prefetch((u8 *)src);
 
@@ -39,67 +41,113 @@
 
 	dump_fifo_data(src, len);
 
-	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);
-}
+	if (!ANOMALY_05000380 && epnum != 0) {
+		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 {
+		SSYNC();
+
+		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);
+
+	}
+}
 /*
  * Unload an endpoint's FIFO
  */
 void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
 {
 	void __iomem *fifo = hw_ep->fifo;
-
-#ifdef CONFIG_BF52x
 	u8 epnum = hw_ep->epnum;
 	u16 dma_reg = 0;
 
-	invalidate_dcache_range((unsigned int)dst,
-		(unsigned int)(dst + len));
+	if (ANOMALY_05000467 && epnum != 0) {
 
-	/* Setup DMA address register */
-	dma_reg = (u16) ((u32) dst & 0xFFFF);
-	bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg);
-	SSYNC();
+		invalidate_dcache_range((unsigned int)dst,
+			(unsigned int)(dst + len));
 
-	dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF);
-	bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg);
-	SSYNC();
+		/* Setup DMA address register */
+		dma_reg = (u16) ((u32) dst & 0xFFFF);
+		bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), 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();
+		dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF);
+		bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg);
+		SSYNC();
 
-	/* Enable the DMA */
-	dma_reg = (epnum << 4) | DMA_ENA | INT_ENA;
-	bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 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();
 
-	/* Wait for compelete */
-	while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum)))
-		cpu_relax();
+		/* Enable the DMA */
+		dma_reg = (epnum << 4) | DMA_ENA | INT_ENA;
+		bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg);
+		SSYNC();
 
-	/* acknowledge dma interrupt */
-	bfin_write_USB_DMA_INTERRUPT(1 << epnum);
-	SSYNC();
+		/* Wait for compelete */
+		while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum)))
+			cpu_relax();
 
-	/* Reset DMA */
-	bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0);
-	SSYNC();
-#else
-	if (unlikely((unsigned long)dst & 0x01))
-		insw_8((unsigned long)fifo, dst,
-			len & 0x01 ? (len >> 1) + 1 : len >> 1);
-	else
-		insw((unsigned long)fifo, dst,
-			len & 0x01 ? (len >> 1) + 1 : len >> 1);
-#endif
+		/* 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 {
+		SSYNC();
+		/* Read the last byte of packet with odd size from address fifo + 4
+		 * to trigger 1 byte access to EP0 FIFO.
+		 */
+		if (len == 1)
+			*dst = (u8)inw((unsigned long)fifo + 4);
+		else {
+			if (unlikely((unsigned long)dst & 0x01))
+				insw_8((unsigned long)fifo, dst, len >> 1);
+			else
+				insw((unsigned long)fifo, dst, len >> 1);
+
+			if (len & 0x01)
+				*(dst + len - 1) = (u8)inw((unsigned long)fifo + 4);
+		}
+	}
 	DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
 			'R', hw_ep->epnum, fifo, len, dst);