Hi Axel,
If this problem is caused by fifo under run on the host side, you may try the following:
1. change the SBUSCFG register to 6 (AHB BURST=U_INCR8). This instructs the USB controller to use INCR8 bursts when possible to access the memory and uses less bus bandwidth
2. tune TXFIFOTHRES in the TXFILLTUNING register. This is normally set to 2 which means the fifo is filled with 2 bursts (64 bytes) before the transfer on the USB bus is started. Setting it to a higher value (ex. 4 = 128 Bytes) will provide more tolerance for latency on the memory bus and thus more less risk for FIFO under run.
Below is the code change to set SBUSCFG=6 and TXFIFOTHRES=8 in kernel 2.6.35 at BSP L2.6.35_10.12.01.
===================================================================================
diff --git a/arch/arm/mach-mx28/usb_dr.c b/arch/arm/mach-mx28/usb_dr.c
index e95b786..6575951 100644
--- a/arch/arm/mach-mx28/usb_dr.c
+++ b/arch/arm/mach-mx28/usb_dr.c
@@ -463,7 +463,7 @@ static int __init usb_dr_init(void)
pr_debug("%s: \n", __func__);
dr_utmi_config.change_ahb_burst = 1;
- dr_utmi_config.ahb_burst_mode = 0;
+ dr_utmi_config.ahb_burst_mode = 6;
#ifdef CONFIG_USB_OTG
dr_utmi_config.operating_mode = FSL_USB2_DR_OTG;
diff --git a/arch/arm/mach-mx28/usb_h1.c b/arch/arm/mach-mx28/usb_h1.c
index 579ce9a..6066143 100644
--- a/arch/arm/mach-mx28/usb_h1.c
+++ b/arch/arm/mach-mx28/usb_h1.c
@@ -202,6 +202,8 @@ static struct fsl_usb2_platform_data usbh1_config = {
.phy_lowpower_suspend = _phy_lowpower_suspend,
.is_wakeup_event = _is_usbh1_wakeup,
.phy_regs = USBPHY1_PHYS_ADDR,
+ .change_ahb_burst = 1,
+ .ahb_burst_mode = 6,
};
static struct fsl_usb2_wakeup_platform_data usbh1_wakeup_config = {
diff --git a/arch/arm/plat-mxs/include/mach/fsl_usb.h b/arch/arm/plat-mxs/include/mach/fsl_usb.h
index f883248..6da125f 100644
--- a/arch/arm/plat-mxs/include/mach/fsl_usb.h
+++ b/arch/arm/plat-mxs/include/mach/fsl_usb.h
@@ -65,6 +65,15 @@ fsl_platform_set_vbus_power(struct fsl_usb2_platform_data *pdata, int on)
/* Set USB AHB burst length for host */
static inline void fsl_platform_set_ahb_burst(struct usb_hcd *hcd)
{
+ struct fsl_usb2_platform_data *pdata;
+ unsigned int temp;
+
+ pdata = hcd->self.controller->platform_data;
+ if (pdata->change_ahb_burst) {
+ temp = readl(hcd->regs + FSL_SOC_USB_SBUSCFG);
+ writel((temp & (~(0x7))) | pdata->ahb_burst_mode,
+ hcd->regs + FSL_SOC_USB_SBUSCFG);
+ }
}
void fsl_phy_usb_utmi_init(struct fsl_xcvr_ops *this);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ea01454..7b1e6a6 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -268,6 +268,9 @@ static int ehci_reset (struct ehci_hcd *ehci)
if (ehci->debug)
dbgp_external_startup();
+ ehci_writel(ehci, TXFIFO_DEFAULT,
+ (u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING));
+
return retval;
}