USB: musb: blackfin: work around anomaly 05000450
[pandora-kernel.git] / drivers / usb / musb / blackfin.c
index 9d49d1c..8e2a1ff 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/cacheflush.h>
 
 #include "musb_core.h"
+#include "musbhsdma.h"
 #include "blackfin.h"
 
 struct bfin_glue {
@@ -322,7 +323,7 @@ static void bfin_musb_try_idle(struct musb *musb, unsigned long timeout)
                mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
 }
 
-static int bfin_musb_get_vbus_status(struct musb *musb)
+static int bfin_musb_vbus_status(struct musb *musb)
 {
        return 0;
 }
@@ -332,6 +333,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 +452,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);
@@ -540,7 +564,7 @@ static struct dev_pm_ops bfin_pm_ops = {
        .resume         = bfin_resume,
 };
 
-#define DEV_PM_OPS     &bfin_pm_op,
+#define DEV_PM_OPS     &bfin_pm_ops
 #else
 #define DEV_PM_OPS     NULL
 #endif
@@ -548,7 +572,7 @@ static struct dev_pm_ops bfin_pm_ops = {
 static struct platform_driver bfin_driver = {
        .remove         = __exit_p(bfin_remove),
        .driver         = {
-               .name   = "musb-bfin",
+               .name   = "musb-blackfin",
                .pm     = DEV_PM_OPS,
        },
 };