aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/blackfin.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/musb/blackfin.c')
-rw-r--r--drivers/usb/musb/blackfin.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c
index 52312e8af213..ae8c39617743 100644
--- a/drivers/usb/musb/blackfin.c
+++ b/drivers/usb/musb/blackfin.c
@@ -21,6 +21,7 @@
#include <asm/cacheflush.h>
#include "musb_core.h"
+#include "musbhsdma.h"
#include "blackfin.h"
struct bfin_glue {
@@ -34,6 +35,7 @@ struct bfin_glue {
*/
void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
{
+ struct musb *musb = hw_ep->musb;
void __iomem *fifo = hw_ep->fifo;
void __iomem *epio = hw_ep->regs;
u8 epnum = hw_ep->epnum;
@@ -42,7 +44,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
musb_writew(epio, MUSB_TXCOUNT, len);
- DBG(4, "TX ep%d fifo %p count %d buf %p, epio %p\n",
+ dev_dbg(musb->controller, "TX ep%d fifo %p count %d buf %p, epio %p\n",
hw_ep->epnum, fifo, len, src, epio);
dump_fifo_data(src, len);
@@ -97,6 +99,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
*/
void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
{
+ struct musb *musb = hw_ep->musb;
void __iomem *fifo = hw_ep->fifo;
u8 epnum = hw_ep->epnum;
@@ -153,7 +156,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
*(dst + len - 1) = (u8)inw((unsigned long)fifo + 4);
}
}
- DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
+ dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n",
'R', hw_ep->epnum, fifo, len, dst);
dump_fifo_data(dst, len);
@@ -278,12 +281,14 @@ static void musb_conn_timer_handler(unsigned long _musb)
}
break;
default:
- DBG(1, "%s state not handled\n", otg_state_string(musb));
+ dev_dbg(musb->controller, "%s state not handled\n",
+ otg_state_string(musb->xceiv->state));
break;
}
spin_unlock_irqrestore(&musb->lock, flags);
- DBG(4, "state is %s\n", otg_state_string(musb));
+ dev_dbg(musb->controller, "state is %s\n",
+ otg_state_string(musb->xceiv->state));
}
static void bfin_musb_enable(struct musb *musb)
@@ -305,9 +310,9 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on)
value = !value;
gpio_set_value(musb->config->gpio_vrsel, value);
- DBG(1, "VBUS %s, devctl %02x "
+ dev_dbg(musb->controller, "VBUS %s, devctl %02x "
/* otg %3x conf %08x prcm %08x */ "\n",
- otg_state_string(musb),
+ otg_state_string(musb->xceiv->state),
musb_readb(musb->mregs, MUSB_DEVCTL));
}
@@ -332,6 +337,27 @@ static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode)
return -EIO;
}
+static int bfin_musb_adjust_channel_params(struct dma_channel *channel,
+ u16 packet_sz, u8 *mode,
+ dma_addr_t *dma_addr, u32 *len)
+{
+ struct musb_dma_channel *musb_channel = channel->private_data;
+
+ /*
+ * Anomaly 05000450 might cause data corruption when using DMA
+ * MODE 1 transmits with short packet. So to work around this,
+ * we truncate all MODE 1 transfers down to a multiple of the
+ * max packet size, and then do the last short packet transfer
+ * (if there is any) using MODE 0.
+ */
+ if (ANOMALY_05000450) {
+ if (musb_channel->transmit && *mode == 1)
+ *len = *len - (*len % packet_sz);
+ }
+
+ return 0;
+}
+
static void bfin_musb_reg_init(struct musb *musb)
{
if (ANOMALY_05000346) {
@@ -430,6 +456,8 @@ static const struct musb_platform_ops bfin_ops = {
.vbus_status = bfin_musb_vbus_status,
.set_vbus = bfin_musb_set_vbus,
+
+ .adjust_channel_params = bfin_musb_adjust_channel_params,
};
static u64 bfin_dmamask = DMA_BIT_MASK(32);