usb: ehci-msm-hsic: Add asynchronous reset to HSIC
Add support for asynchronous block reset to the HSIC hardware.
In platforms that uses an asynchronous reset methodology,
the HSIC alt_core_clk is not presented.
Change-Id: I0dc0e1bf294260a5530e01660d970cc939a9dbec
Signed-off-by: Ofir Cohen <ofirc@codeaurora.org>
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 57598c8..1141a24 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -575,20 +575,53 @@
{
int ret;
- ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
- if (ret) {
- dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
- return;
+ /* alt_core_clk exists in targets that do not use asynchronous reset */
+ if (!IS_ERR(mehci->alt_core_clk)) {
+ ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
+ if (ret) {
+ dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
+ return;
+ }
+
+ /* Since a hw bug, turn off the clock before complete reset */
+ clk_disable(mehci->core_clk);
+
+ ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
+ ret);
+
+ usleep_range(10000, 12000);
+
+ clk_enable(mehci->core_clk);
+ } else {
+ /* Using asynchronous block reset to the hardware */
+ clk_disable_unprepare(mehci->core_clk);
+ clk_disable_unprepare(mehci->phy_clk);
+ clk_disable_unprepare(mehci->cal_clk);
+ clk_disable_unprepare(mehci->ahb_clk);
+
+ ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
+ if (ret) {
+ dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
+ return;
+ }
+ usleep_range(10000, 12000);
+
+ ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
+ ret);
+ /*
+ * Required delay between the deassertion and
+ * clock enablement.
+ */
+ ndelay(200);
+ clk_prepare_enable(mehci->core_clk);
+ clk_prepare_enable(mehci->phy_clk);
+ clk_prepare_enable(mehci->cal_clk);
+ clk_prepare_enable(mehci->ahb_clk);
}
- clk_disable(mehci->core_clk);
-
- ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
- if (ret)
- dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
-
- usleep_range(10000, 12000);
-
- clk_enable(mehci->core_clk);
}
#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
@@ -1286,7 +1319,8 @@
return ret;
}
- /* alt_core_clk is for LINK to be used during PHY RESET
+ /* alt_core_clk is for LINK to be used during PHY RESET in
+ * targets on which link does NOT use asynchronous reset methodology.
* clock rate appropriately set by target specific clock driver */
mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
if (IS_ERR(mehci->alt_core_clk))