aboutsummaryrefslogtreecommitdiffstats
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 {
148 * @ctrl_buff: Buffer for EP0 control requests. 148 * @ctrl_buff: Buffer for EP0 control requests.
149 * @ctrl_req: Request for EP0 control packets. 149 * @ctrl_req: Request for EP0 control packets.
150 * @setup: NAK management for EP0 SETUP 150 * @setup: NAK management for EP0 SETUP
151 * @last_rst: Time of last reset
151 * @eps: The endpoints being supplied to the gadget framework 152 * @eps: The endpoints being supplied to the gadget framework
152 */ 153 */
153struct s3c_hsotg { 154struct s3c_hsotg {
@@ -175,6 +176,7 @@ struct s3c_hsotg {
175 176
176 struct usb_gadget gadget; 177 struct usb_gadget gadget;
177 unsigned int setup; 178 unsigned int setup;
179 unsigned long last_rst;
178 struct s3c_hsotg_ep eps[]; 180 struct s3c_hsotg_ep eps[];
179}; 181};
180 182
@@ -2377,23 +2379,26 @@ irq_retry:
2377 } 2379 }
2378 2380
2379 if (gintsts & S3C_GINTSTS_USBRst) { 2381 if (gintsts & S3C_GINTSTS_USBRst) {
2382
2383 u32 usb_status = readl(hsotg->regs + S3C_GOTGCTL);
2384
2380 dev_info(hsotg->dev, "%s: USBRst\n", __func__); 2385 dev_info(hsotg->dev, "%s: USBRst\n", __func__);
2381 dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", 2386 dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
2382 readl(hsotg->regs + S3C_GNPTXSTS)); 2387 readl(hsotg->regs + S3C_GNPTXSTS));
2383 2388
2384 writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); 2389 writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS);
2385 2390
2386 kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); 2391 if (usb_status & S3C_GOTGCTL_BSESVLD) {
2392 if (time_after(jiffies, hsotg->last_rst +
2393 msecs_to_jiffies(200))) {
2387 2394
2388 /* it seems after a reset we can end up with a situation 2395 kill_all_requests(hsotg, &hsotg->eps[0],
2389 * where the TXFIFO still has data in it... the docs 2396 -ECONNRESET, true);
2390 * suggest resetting all the fifos, so use the init_fifo
2391 * code to relayout and flush the fifos.
2392 */
2393 2397
2394 s3c_hsotg_init_fifo(hsotg); 2398 s3c_hsotg_core_init(hsotg);
2395 2399 hsotg->last_rst = jiffies;
2396 s3c_hsotg_enqueue_setup(hsotg); 2400 }
2401 }
2397 } 2402 }
2398 2403
2399 /* check both FIFOs */ 2404 /* check both FIFOs */
@@ -2436,6 +2441,7 @@ irq_retry:
2436 writel(S3C_GINTSTS_USBSusp, hsotg->regs + S3C_GINTSTS); 2441 writel(S3C_GINTSTS_USBSusp, hsotg->regs + S3C_GINTSTS);
2437 2442
2438 call_gadget(hsotg, suspend); 2443 call_gadget(hsotg, suspend);
2444 s3c_hsotg_disconnect(hsotg);
2439 } 2445 }
2440 2446
2441 if (gintsts & S3C_GINTSTS_WkUpInt) { 2447 if (gintsts & S3C_GINTSTS_WkUpInt) {
@@ -2448,6 +2454,8 @@ irq_retry:
2448 if (gintsts & S3C_GINTSTS_ErlySusp) { 2454 if (gintsts & S3C_GINTSTS_ErlySusp) {
2449 dev_dbg(hsotg->dev, "S3C_GINTSTS_ErlySusp\n"); 2455 dev_dbg(hsotg->dev, "S3C_GINTSTS_ErlySusp\n");
2450 writel(S3C_GINTSTS_ErlySusp, hsotg->regs + S3C_GINTSTS); 2456 writel(S3C_GINTSTS_ErlySusp, hsotg->regs + S3C_GINTSTS);
2457
2458 s3c_hsotg_disconnect(hsotg);
2451 } 2459 }
2452 2460
2453 /* these next two seem to crop-up occasionally causing the core 2461 /* 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,
2823 } 2831 }
2824 2832
2825 s3c_hsotg_core_init(hsotg); 2833 s3c_hsotg_core_init(hsotg);
2826 2834 hsotg->last_rst = jiffies;
2827 dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); 2835 dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
2828 return 0; 2836 return 0;
2829 2837