]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/usb/gadget/s3c-hsotg.c
USB: s3c-hsotg: Re-initialise all FIFOs on USB bus reset
[net-next-2.6.git] / drivers / usb / gadget / s3c-hsotg.c
index 26193eceb3231d48c06e98b29a09cf9849b319f5..9d32c9ff737d92f8ba88066db1893d18098ccabf 100644 (file)
@@ -91,7 +91,9 @@ struct s3c_hsotg_req;
  * For periodic IN endpoints, we have fifo_size and fifo_load to try
  * and keep track of the amount of data in the periodic FIFO for each
  * of these as we don't have a status register that tells us how much
- * is in each of them.
+ * is in each of them. (note, this may actually be useless information
+ * as in shared-fifo mode periodic in acts like a single-frame packet
+ * buffer than a fifo)
  */
 struct s3c_hsotg_ep {
        struct usb_ep           ep;
@@ -310,11 +312,11 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
                hsotg->regs + S3C_GNPTXFSIZ);
        */
 
-       /* set FIFO sizes to 2048/0x1C0 */
+       /* set FIFO sizes to 2048/1024 */
 
        writel(2048, hsotg->regs + S3C_GRXFSIZ);
        writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) |
-              S3C_GNPTXFSIZ_NPTxFDep(0x1C0),
+              S3C_GNPTXFSIZ_NPTxFDep(1024),
               hsotg->regs + S3C_GNPTXFSIZ);
 
        /* arange all the rest of the TX FIFOs, as some versions of this
@@ -474,6 +476,14 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
 
                size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
 
+               /* if shared fifo, we cannot write anything until the
+                * previous data has been completely sent.
+                */
+               if (hs_ep->fifo_load != 0) {
+                       s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
+                       return -ENOSPC;
+               }
+
                dev_dbg(hsotg->dev, "%s: left=%d, load=%d, fifo=%d, size %d\n",
                        __func__, size_left,
                        hs_ep->size_loaded, hs_ep->fifo_load, hs_ep->fifo_size);
@@ -505,6 +515,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
                }
 
                can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts);
+               can_write *= 4; /* fifo size is in 32bit quantities. */
        }
 
        dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n",
@@ -2071,17 +2082,12 @@ irq_retry:
                kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true);
 
                /* it seems after a reset we can end up with a situation
-                * where the TXFIFO still has data in it... try flushing
-                * it to remove anything that may still be in it.
+                * where the TXFIFO still has data in it... the docs
+                * suggest resetting all the fifos, so use the init_fifo
+                * code to relayout and flush the fifos.
                 */
 
-               if (1) {
-                       writel(S3C_GRSTCTL_TxFNum(0) | S3C_GRSTCTL_TxFFlsh,
-                              hsotg->regs + S3C_GRSTCTL);
-
-                       dev_info(hsotg->dev, "GNPTXSTS=%08x\n",
-                                readl(hsotg->regs + S3C_GNPTXSTS));
-               }
+               s3c_hsotg_init_fifo(hsotg);
 
                s3c_hsotg_enqueue_setup(hsotg);
 
@@ -2732,7 +2738,7 @@ static void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg,
         */
 
        ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum));
-       hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo);
+       hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4;
 
        /* if we're using dma, we need to set the next-endpoint pointer
         * to be something valid.