Merge tag 'usb-ci-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter...
[platform/kernel/linux-rpi.git] / drivers / usb / chipidea / core.c
index 87ae3c8..aa40e51 100644 (file)
@@ -155,6 +155,7 @@ u32 hw_read_intr_status(struct ci_hdrc *ci)
 
 /**
  * hw_port_test_set: writes port test mode (execute without interruption)
+ * @ci: the controller
  * @mode: new value
  *
  * This function returns an error code
@@ -1270,6 +1271,29 @@ static void ci_controller_suspend(struct ci_hdrc *ci)
        enable_irq(ci->irq);
 }
 
+/*
+ * Handle the wakeup interrupt triggered by extcon connector
+ * We need to call ci_irq again for extcon since the first
+ * interrupt (wakeup int) only let the controller be out of
+ * low power mode, but not handle any interrupts.
+ */
+static void ci_extcon_wakeup_int(struct ci_hdrc *ci)
+{
+       struct ci_hdrc_cable *cable_id, *cable_vbus;
+       u32 otgsc = hw_read_otgsc(ci, ~0);
+
+       cable_id = &ci->platdata->id_extcon;
+       cable_vbus = &ci->platdata->vbus_extcon;
+
+       if (!IS_ERR(cable_id->edev) && ci->is_otg &&
+               (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS))
+               ci_irq(ci->irq, ci);
+
+       if (!IS_ERR(cable_vbus->edev) && ci->is_otg &&
+               (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS))
+               ci_irq(ci->irq, ci);
+}
+
 static int ci_controller_resume(struct device *dev)
 {
        struct ci_hdrc *ci = dev_get_drvdata(dev);
@@ -1302,6 +1326,7 @@ static int ci_controller_resume(struct device *dev)
                enable_irq(ci->irq);
                if (ci_otg_is_fsm_mode(ci))
                        ci_otg_fsm_wakeup_by_srp(ci);
+               ci_extcon_wakeup_int(ci);
        }
 
        return 0;