diff options
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.patch | 71 |
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 + |