|
@@ -104,7 +104,31 @@ void ci_handle_vbus_change(struct ci_hdrc *ci)
|
|
|
usb_gadget_vbus_disconnect(&ci->gadget);
|
|
|
}
|
|
|
|
|
|
-#define CI_VBUS_STABLE_TIMEOUT_MS 5000
|
|
|
+/**
|
|
|
+ * When we switch to device mode, the vbus value should be lower
|
|
|
+ * than OTGSC_BSV before connecting to host.
|
|
|
+ *
|
|
|
+ * @ci: the controller
|
|
|
+ *
|
|
|
+ * This function returns an error code if timeout
|
|
|
+ */
|
|
|
+static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
|
|
|
+{
|
|
|
+ unsigned long elapse = jiffies + msecs_to_jiffies(5000);
|
|
|
+ u32 mask = OTGSC_BSV;
|
|
|
+
|
|
|
+ while (hw_read_otgsc(ci, mask)) {
|
|
|
+ if (time_after(jiffies, elapse)) {
|
|
|
+ dev_err(ci->dev, "timeout waiting for %08x in OTGSC\n",
|
|
|
+ mask);
|
|
|
+ return -ETIMEDOUT;
|
|
|
+ }
|
|
|
+ msleep(20);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void ci_handle_id_switch(struct ci_hdrc *ci)
|
|
|
{
|
|
|
enum ci_role role = ci_otg_role(ci);
|
|
@@ -116,9 +140,11 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
|
|
|
ci_role_stop(ci);
|
|
|
|
|
|
if (role == CI_ROLE_GADGET)
|
|
|
- /* wait vbus lower than OTGSC_BSV */
|
|
|
- hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
|
|
|
- CI_VBUS_STABLE_TIMEOUT_MS);
|
|
|
+ /*
|
|
|
+ * wait vbus lower than OTGSC_BSV before connecting
|
|
|
+ * to host
|
|
|
+ */
|
|
|
+ hw_wait_vbus_lower_bsv(ci);
|
|
|
|
|
|
ci_role_start(ci, role);
|
|
|
}
|