diff options
Diffstat (limited to 'drivers/usb/gadget/s3c-hsotg.c')
-rw-r--r-- | drivers/usb/gadget/s3c-hsotg.c | 28 |
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 | */ |
153 | struct s3c_hsotg { | 154 | struct 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 | ||