summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/s3c-hsotg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/s3c-hsotg.c')
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 7e3b59106e67..ca9041634c04 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -148,6 +148,7 @@ struct s3c_hsotg_ep {
* @ctrl_buff: Buffer for EP0 control requests.
* @ctrl_req: Request for EP0 control packets.
* @setup: NAK management for EP0 SETUP
+ * @last_rst: Time of last reset
* @eps: The endpoints being supplied to the gadget framework
*/
struct s3c_hsotg {
@@ -175,6 +176,7 @@ struct s3c_hsotg {
struct usb_gadget gadget;
unsigned int setup;
+ unsigned long last_rst;
struct s3c_hsotg_ep eps[];
};
@@ -2377,23 +2379,26 @@ irq_retry:
}
if (gintsts & S3C_GINTSTS_USBRst) {
+
+ u32 usb_status = readl(hsotg->regs + S3C_GOTGCTL);
+
dev_info(hsotg->dev, "%s: USBRst\n", __func__);
dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
readl(hsotg->regs + S3C_GNPTXSTS));
writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS);
- kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true);
+ if (usb_status & S3C_GOTGCTL_BSESVLD) {
+ if (time_after(jiffies, hsotg->last_rst +
+ msecs_to_jiffies(200))) {
- /* it seems after a reset we can end up with a situation
- * 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.
- */
+ kill_all_requests(hsotg, &hsotg->eps[0],
+ -ECONNRESET, true);
- s3c_hsotg_init_fifo(hsotg);
-
- s3c_hsotg_enqueue_setup(hsotg);
+ s3c_hsotg_core_init(hsotg);
+ hsotg->last_rst = jiffies;
+ }
+ }
}
/* check both FIFOs */
@@ -2436,6 +2441,7 @@ irq_retry:
writel(S3C_GINTSTS_USBSusp, hsotg->regs + S3C_GINTSTS);
call_gadget(hsotg, suspend);
+ s3c_hsotg_disconnect(hsotg);
}
if (gintsts & S3C_GINTSTS_WkUpInt) {
@@ -2448,6 +2454,8 @@ irq_retry:
if (gintsts & S3C_GINTSTS_ErlySusp) {
dev_dbg(hsotg->dev, "S3C_GINTSTS_ErlySusp\n");
writel(S3C_GINTSTS_ErlySusp, hsotg->regs + S3C_GINTSTS);
+
+ s3c_hsotg_disconnect(hsotg);
}
/* these next two seem to crop-up occasionally causing the core
@@ -2823,7 +2831,7 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver,
}
s3c_hsotg_core_init(hsotg);
-
+ hsotg->last_rst = jiffies;
dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
return 0;