|
@@ -2378,6 +2378,30 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
|
|
|
dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state);
|
|
|
}
|
|
|
|
|
|
+static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc,
|
|
|
+ unsigned int evtinfo)
|
|
|
+{
|
|
|
+ unsigned int is_ss = evtinfo & BIT(4);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * WORKAROUND: DWC3 revison 2.20a with hibernation support
|
|
|
+ * have a known issue which can cause USB CV TD.9.23 to fail
|
|
|
+ * randomly.
|
|
|
+ *
|
|
|
+ * Because of this issue, core could generate bogus hibernation
|
|
|
+ * events which SW needs to ignore.
|
|
|
+ *
|
|
|
+ * Refers to:
|
|
|
+ *
|
|
|
+ * STAR#9000546576: Device Mode Hibernation: Issue in USB 2.0
|
|
|
+ * Device Fallback from SuperSpeed
|
|
|
+ */
|
|
|
+ if (is_ss ^ (dwc->speed == USB_SPEED_SUPER))
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* enter hibernation here */
|
|
|
+}
|
|
|
+
|
|
|
static void dwc3_gadget_interrupt(struct dwc3 *dwc,
|
|
|
const struct dwc3_event_devt *event)
|
|
|
{
|
|
@@ -2394,6 +2418,13 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
|
|
|
case DWC3_DEVICE_EVENT_WAKEUP:
|
|
|
dwc3_gadget_wakeup_interrupt(dwc);
|
|
|
break;
|
|
|
+ case DWC3_DEVICE_EVENT_HIBER_REQ:
|
|
|
+ if (dev_WARN_ONCE(dwc->dev, !dwc->has_hibernation,
|
|
|
+ "unexpected hibernation event\n"))
|
|
|
+ break;
|
|
|
+
|
|
|
+ dwc3_gadget_hibernation_interrupt(dwc, event->event_info);
|
|
|
+ break;
|
|
|
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
|
|
|
dwc3_gadget_linksts_change_interrupt(dwc, event->event_info);
|
|
|
break;
|