From f09ce1432b13cf796c8e23152195d04456d89cc6 Mon Sep 17 00:00:00 2001 From: SEO HOYOUNG Date: Mon, 13 May 2019 19:44:06 +0900 Subject: [PATCH] [RAMEN9610-19639][COMMON] usb: add DCTL run/stop when enumeration fail. Change-Id: I0da546bc9c2053c3f5e8f2867022577919c3c74f Signed-off-by: SEO HOYOUNG --- drivers/usb/dwc3/core.h | 5 ++++ drivers/usb/dwc3/otg.c | 59 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index f13c59f62062..de1e9c576a26 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -825,6 +825,8 @@ struct dwc3_scratchpad_array { __le64 dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS]; }; +#define CHG_CONNECTED_DELAY_TIME (10000*HZ/1000) /* 10s */ + /** * struct dwc3 - representation of our controller * @drd_work: workqueue used for role swapping @@ -955,6 +957,9 @@ struct dwc3 { struct dwc3_request ep0_usb_req; struct completion ep0_in_setup; + /* check device state */ + struct timer_list usb_connect_timer; + /* device lock */ spinlock_t lock; diff --git a/drivers/usb/dwc3/otg.c b/drivers/usb/dwc3/otg.c index 2f756a5f2b1d..d04131808750 100755 --- a/drivers/usb/dwc3/otg.c +++ b/drivers/usb/dwc3/otg.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef CONFIG_EXYNOS_PD #include #endif @@ -320,6 +321,54 @@ err1: return ret; } +static void retry_configuration(unsigned long data) +{ + struct dwc3 *dwc = (struct dwc3 *)data; + struct usb_gadget *gadget = &dwc->gadget; + struct usb_composite_dev *cdev = get_gadget_data(gadget); + u32 reg; + + pr_info("%s: +++\n", __func__); + + if (!cdev->config) { + + if (dwc->dr_mode == USB_DR_MODE_HOST) + return; + + pr_info("%s: retry USB enumeration\n", __func__); + + /* stop */ + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg &= ~DWC3_DCTL_RUN_STOP; + + if (dwc->has_hibernation) + reg &= ~DWC3_DCTL_KEEP_CONNECT; + + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + mdelay(500); + + /* run */ + if (dwc->revision <= DWC3_REVISION_187A) { + reg &= ~DWC3_DCTL_TRGTULST_MASK; + reg |= DWC3_DCTL_TRGTULST_RX_DET; + } + + if (dwc->revision >= DWC3_REVISION_194A) + reg &= ~DWC3_DCTL_KEEP_CONNECT; + + reg |= DWC3_DCTL_RUN_STOP; + + if (dwc->has_hibernation) + reg |= DWC3_DCTL_KEEP_CONNECT; + + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + + } else { + pr_info("%s: already configuration done!!\n", __func__); + } + pr_info("%s: ---\n", __func__); +} + static int dwc3_otg_start_gadget(struct otg_fsm *fsm, int on) { struct usb_otg *otg = fsm->otg; @@ -363,7 +412,17 @@ static int dwc3_otg_start_gadget(struct otg_fsm *fsm, int on) goto err2; } + pr_info("%s: start check usb configuration timer\n", __func__); + init_timer(&dwc->usb_connect_timer); + dwc->usb_connect_timer.expires = jiffies + CHG_CONNECTED_DELAY_TIME; + dwc->usb_connect_timer.function = retry_configuration; + dwc->usb_connect_timer.data = (unsigned long)dwc; + add_timer(&dwc->usb_connect_timer); + + } else { + del_timer_sync(&dwc->usb_connect_timer); + if (dwc->is_not_vbus_pad) dwc3_gadget_disconnect_proc(dwc); /* avoid missing disconnect interrupt */ -- 2.20.1