summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2014-11-26 13:44:32 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-11-26 09:28:12 -0800
commitcdd278f21eea55412dd0c5bc468bbdfb0639879b (patch)
treef0a69b7d940161898c6ca7ee71cf02de946f9d8a /drivers/usb
parent947c88592f17bd299ff677049c3cda36cc6f93dd (diff)
usb: chipidea: add controller reset API
Add controller reset API, currently it is used for device mode only. It may be used for host/otg driver in future. Ususally, we need this API for dual-role switch and back from hibernation suspend to let the controller at default state. Signed-off-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/chipidea/core.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index bd74f27a95e5..48b25d9ebf82 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -385,20 +385,44 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
}
/**
- * hw_device_reset: resets chip (execute without interruption)
+ * hw_controller_reset: do controller reset
* @ci: the controller
*
* This function returns an error code
*/
+static int hw_controller_reset(struct ci_hdrc *ci)
+{
+ int count = 0;
+
+ hw_write(ci, OP_USBCMD, USBCMD_RST, USBCMD_RST);
+ while (hw_read(ci, OP_USBCMD, USBCMD_RST)) {
+ udelay(10);
+ if (count++ > 1000)
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+/**
+ * hw_device_reset: resets chip (execute without interruption)
+ * @ci: the controller
+ *
+ * This function returns an error code
+ */
int hw_device_reset(struct ci_hdrc *ci, u32 mode)
{
+ int ret;
+
/* should flush & stop before reset */
hw_write(ci, OP_ENDPTFLUSH, ~0, ~0);
hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
- hw_write(ci, OP_USBCMD, USBCMD_RST, USBCMD_RST);
- while (hw_read(ci, OP_USBCMD, USBCMD_RST))
- udelay(10); /* not RTOS friendly */
+ ret = hw_controller_reset(ci);
+ if (ret) {
+ dev_err(ci->dev, "error resetting controller, ret=%d\n", ret);
+ return ret;
+ }
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,