|
@@ -21,6 +21,7 @@
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/cacheflush.h>
|
|
|
|
|
|
#include "musb_core.h"
|
|
#include "musb_core.h"
|
|
|
|
+#include "musbhsdma.h"
|
|
#include "blackfin.h"
|
|
#include "blackfin.h"
|
|
|
|
|
|
struct bfin_glue {
|
|
struct bfin_glue {
|
|
@@ -332,6 +333,27 @@ static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode)
|
|
return -EIO;
|
|
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)
|
|
static void bfin_musb_reg_init(struct musb *musb)
|
|
{
|
|
{
|
|
if (ANOMALY_05000346) {
|
|
if (ANOMALY_05000346) {
|
|
@@ -430,6 +452,8 @@ static const struct musb_platform_ops bfin_ops = {
|
|
|
|
|
|
.vbus_status = bfin_musb_vbus_status,
|
|
.vbus_status = bfin_musb_vbus_status,
|
|
.set_vbus = bfin_musb_set_vbus,
|
|
.set_vbus = bfin_musb_set_vbus,
|
|
|
|
+
|
|
|
|
+ .adjust_channel_params = bfin_musb_adjust_channel_params,
|
|
};
|
|
};
|
|
|
|
|
|
static u64 bfin_dmamask = DMA_BIT_MASK(32);
|
|
static u64 bfin_dmamask = DMA_BIT_MASK(32);
|