USB: dwc3-msm: Perform HW reinitialization on HC died error
USB core provides atomic notifier that can be used by platform drivers to perform hardware reset/recovery on HC died error. This error is fatal and requires complete hardware re-initialization. This will remove and add hcd again. CRs-fixed: 1048766 Change-Id: Ic889ef002717a8fa33e9b7c27fab14a8778bba89 Signed-off-by: Manu Gautam <mgautam@codeaurora.org> Signed-off-by: Chandana Kishori Chiluveru <cchiluve@codeaurora.org> Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
This commit is contained in:
parent
2d28ff0953
commit
ccca5c248d
1 changed files with 35 additions and 2 deletions
|
@ -204,6 +204,8 @@ struct dwc3_msm {
|
|||
|
||||
unsigned int irq_to_affin;
|
||||
struct notifier_block dwc3_cpu_notifier;
|
||||
struct notifier_block usbdev_nb;
|
||||
bool hc_died;
|
||||
|
||||
struct extcon_dev *extcon_vbus;
|
||||
struct extcon_dev *extcon_id;
|
||||
|
@ -1484,6 +1486,33 @@ static void dwc3_restart_usb_work(struct work_struct *w)
|
|||
flush_delayed_work(&mdwc->sm_work);
|
||||
}
|
||||
|
||||
static int msm_dwc3_usbdev_notify(struct notifier_block *self,
|
||||
unsigned long action, void *priv)
|
||||
{
|
||||
struct dwc3_msm *mdwc = container_of(self, struct dwc3_msm, usbdev_nb);
|
||||
struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
|
||||
struct usb_bus *bus = priv;
|
||||
|
||||
/* Interested only in recovery when HC dies */
|
||||
if (action != USB_BUS_DIED)
|
||||
return 0;
|
||||
|
||||
dev_dbg(mdwc->dev, "%s initiate recovery from hc_died\n", __func__);
|
||||
/* Recovery already under process */
|
||||
if (mdwc->hc_died)
|
||||
return 0;
|
||||
|
||||
if (bus->controller != &dwc->xhci->dev) {
|
||||
dev_dbg(mdwc->dev, "%s event for diff HCD\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mdwc->hc_died = true;
|
||||
schedule_delayed_work(&mdwc->sm_work, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check whether the DWC3 requires resetting the ep
|
||||
* after going to Low Power Mode (lpm)
|
||||
|
@ -3154,6 +3183,8 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
|
|||
mdwc->host_nb.notifier_call = dwc3_msm_host_notifier;
|
||||
usb_register_notify(&mdwc->host_nb);
|
||||
|
||||
mdwc->usbdev_nb.notifier_call = msm_dwc3_usbdev_notify;
|
||||
usb_register_atomic_notify(&mdwc->usbdev_nb);
|
||||
/*
|
||||
* FIXME If micro A cable is disconnected during system suspend,
|
||||
* xhci platform device will be removed before runtime pm is
|
||||
|
@ -3197,6 +3228,7 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
|
|||
} else {
|
||||
dev_dbg(mdwc->dev, "%s: turn off host\n", __func__);
|
||||
|
||||
usb_unregister_atomic_notify(&mdwc->usbdev_nb);
|
||||
if (!IS_ERR(mdwc->vbus_reg))
|
||||
ret = regulator_disable(mdwc->vbus_reg);
|
||||
if (ret) {
|
||||
|
@ -3488,11 +3520,12 @@ static void dwc3_otg_sm_work(struct work_struct *w)
|
|||
break;
|
||||
|
||||
case OTG_STATE_A_HOST:
|
||||
if (test_bit(ID, &mdwc->inputs)) {
|
||||
dev_dbg(mdwc->dev, "id\n");
|
||||
if (test_bit(ID, &mdwc->inputs) || mdwc->hc_died) {
|
||||
dev_dbg(mdwc->dev, "id || hc_died\n");
|
||||
dwc3_otg_start_host(mdwc, 0);
|
||||
mdwc->otg_state = OTG_STATE_B_IDLE;
|
||||
mdwc->vbus_retry_count = 0;
|
||||
mdwc->hc_died = false;
|
||||
work = 1;
|
||||
} else {
|
||||
dev_dbg(mdwc->dev, "still in a_host state. Resuming root hub.\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue