summaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-2.6.35/rx1950/0002-s3c2410_udc-2440-dual-packet-workaround.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.35/rx1950/0002-s3c2410_udc-2440-dual-packet-workaround.patch')
-rw-r--r--recipes/linux/linux-2.6.35/rx1950/0002-s3c2410_udc-2440-dual-packet-workaround.patch71
1 files changed, 71 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.35/rx1950/0002-s3c2410_udc-2440-dual-packet-workaround.patch b/recipes/linux/linux-2.6.35/rx1950/0002-s3c2410_udc-2440-dual-packet-workaround.patch
new file mode 100644
index 0000000000..bd9a8b12e7
--- /dev/null
+++ b/recipes/linux/linux-2.6.35/rx1950/0002-s3c2410_udc-2440-dual-packet-workaround.patch
@@ -0,0 +1,71 @@
+From fc47d51f262ec6d0a4601fe37ac6478e30d68060 Mon Sep 17 00:00:00 2001
+From: Vasily Khoruzhick <anarsoul@gmail.com>
+Date: Thu, 24 Sep 2009 22:17:47 +0300
+Subject: [PATCH 02/20] s3c2410_udc: 2440 dual packet workaround
+
+This is a patch that seems to make the USB hangs on the S3C2440 go away.
+At least a good amount of ping torture didn't make them come back so far.
+
+The issue is that, if there are several back-to-back packets, sometimes no
+interrupt is generated for one of them. This seems to be caused by the
+mysterious dual packet mode, which the USB hardware enters automatically
+if the endpoint size is half that of the FIFO. (On the 2440, this is the
+normal situation for bulk data endpoints.)
+
+There is also a timing factor in this. I think what happens is that the USB
+hardware automatically sends an acknowledgement if there is only one packet
+in the FIFO (the FIFO has space for two). If another packet arrives before
+the host has retrieved and acknowledged the previous one, no interrupt is
+generated for that second one.
+
+However, there may be an indication. There is one undocumented bit (none
+of the 244x manuals document it), OUT_CRS1_REG[1], that seems to be set
+suspiciously often when this condition occurs. There is also
+CLR_DATA_TOGGLE, OUT_CRS1_REG[7], which may have a function related to
+this. (The Samsung manual is rather terse on that, as usual.)
+
+This needs to be examined further. For now, the patch seems to do the
+trick.
+
+Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
+---
+ drivers/usb/gadget/s3c2410_udc.c | 16 +++++++++++++++-
+ 1 files changed, 15 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
+index ea2b3c7..fed323c 100644
+--- a/drivers/usb/gadget/s3c2410_udc.c
++++ b/drivers/usb/gadget/s3c2410_udc.c
+@@ -902,7 +902,7 @@ static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
+ int pwr_reg;
+ int ep0csr;
+ int i;
+- u32 idx;
++ u32 idx, idx2;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->lock, flags);
+@@ -1017,6 +1017,20 @@ static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
+ }
+ }
+
++ /* what else causes this interrupt? a receive! who is it? */
++ if (!usb_status && !usbd_status && !pwr_reg && !ep0csr) {
++ for (i = 1; i < S3C2410_ENDPOINTS; i++) {
++ idx2 = udc_read(S3C2410_UDC_INDEX_REG);
++ udc_write(i, S3C2410_UDC_INDEX_REG);
++
++ if (udc_read(S3C2410_UDC_OUT_CSR1_REG) & 0x1)
++ s3c2410_udc_handle_ep(&dev->ep[i]);
++
++ /* restore index */
++ udc_write(idx2, S3C2410_UDC_INDEX_REG);
++ }
++ }
++
+ dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD);
+
+ /* Restore old index */
+--
+1.7.2.2
+