summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy.green@linaro.org>2014-12-19 13:28:22 +0800
committerAndy Green <andy.green@linaro.org>2014-12-26 18:43:09 +0800
commit8b301eb471b45aba1433dbcd9baeff86e603dbc3 (patch)
tree7d3530ab4e99d680b418ab4c1144ed392f0a915c
parent04cce957b708289e9ec293eaf2d0572ae6496f1e (diff)
Signed-off-by: Andy Green <andy.green@linaro.org>
-rw-r--r--drivers/usb/phy/phy-msm-usb.c88
1 files changed, 75 insertions, 13 deletions
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index 000fd892455f..674438b1d429 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -43,6 +43,7 @@
#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/regulator/consumer.h>
+#include <linux/clk/msm-clk.h>
#define MSM_USB_BASE (motg->regs)
#define DRIVER_NAME "msm_otg"
@@ -64,6 +65,11 @@
#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
#define USB_PHY_SUSP_DIG_VOL 500000 /* uV */
+#define AHB2AHB_BYPASS BIT(31)
+#define AHB2AHB_BYPASS_BIT_MASK BIT(31)
+#define AHB2AHB_BYPASS_CLEAR (0 << 31)
+
+
enum vdd_levels {
VDD_LEVEL_NONE = 0,
VDD_LEVEL_MIN,
@@ -261,26 +267,47 @@ static int msm_phy_notify_disconnect(struct usb_phy *phy,
static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert)
{
- int ret;
+ int ret = 0;
+#if 0
if (motg->pdata->link_clk_reset)
ret = motg->pdata->link_clk_reset(motg->clk, assert);
- else if (assert)
- ret = reset_control_assert(motg->link_rst);
- else
- ret = reset_control_deassert(motg->link_rst);
+ else if (assert) {
+ if (motg->link_rst)
+ ret = reset_control_assert(motg->link_rst);
+ } else
+ if (motg->link_rst)
+ ret = reset_control_deassert(motg->link_rst);
if (ret)
dev_err(motg->phy.dev, "usb link clk reset %s failed\n",
assert ? "assert" : "deassert");
+#endif
+ if (assert) {
+ /* Using asynchronous block reset to the hardware */
+ dev_dbg(motg->phy.dev, "block_reset ASSERT\n");
+ clk_disable_unprepare(motg->pclk);
+ clk_disable_unprepare(motg->core_clk);
+ ret = clk_reset(motg->core_clk, CLK_RESET_ASSERT);
+ if (ret)
+ pr_err("%s: reset failed %d\n", __func__, ret);
+ } else {
+ ret = clk_reset(motg->core_clk, CLK_RESET_DEASSERT);
+ ndelay(200);
+ ret = clk_prepare_enable(motg->core_clk);
+// WARN(ret, "USB core_clk enable failed\n");
+ ret = clk_prepare_enable(motg->pclk);
+// WARN(ret, "USB pclk enable failed\n");
+ }
+ return 0;
return ret;
}
static int msm_otg_phy_clk_reset(struct msm_otg *motg)
{
int ret = 0;
-
+#if 0
if (motg->pdata->phy_clk_reset)
ret = motg->pdata->phy_clk_reset(motg->phy_reset_clk);
else if (motg->phy_rst)
@@ -288,6 +315,39 @@ static int msm_otg_phy_clk_reset(struct msm_otg *motg)
if (ret)
dev_err(motg->phy.dev, "usb phy clk reset failed\n");
+#endif
+
+ u32 val;
+
+ /*
+ * * AHB2AHB Bypass mode shouldn't be enable before doing
+ * * async clock reset. If it is enable, disable the same.
+ * */
+ val = readl_relaxed(USB_AHBMODE);
+ if (val & AHB2AHB_BYPASS) {
+ pr_err("%s(): AHB2AHB_BYPASS SET: AHBMODE:%x\n",
+ __func__, val);
+ val &= ~AHB2AHB_BYPASS_BIT_MASK;
+ writel_relaxed(val | AHB2AHB_BYPASS_CLEAR, USB_AHBMODE);
+ pr_err("%s(): AHBMODE: %x\n", __func__,
+ readl_relaxed(USB_AHBMODE));
+ }
+
+ ret = msm_otg_link_clk_reset(motg, 1);
+ if (ret)
+ return ret;
+
+ /* wait for 1ms delay as suggested in HPG. */
+ usleep_range(1000, 1200);
+
+ ret = msm_otg_link_clk_reset(motg, 0);
+ if (ret)
+ return ret;
+
+ val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK;
+ writel(val | PORTSC_PTS_ULPI, USB_PORTSC);
+
+ dev_info(motg->phy.dev, "phy_reset: success\n");
return ret;
}
@@ -1463,13 +1523,13 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
id = of_match_device(msm_otg_dt_match, &pdev->dev);
pdata->phy_type = (enum msm_usb_phy_type) id->data;
- motg->link_rst = devm_reset_control_get(&pdev->dev, "link");
- if (IS_ERR(motg->link_rst))
- return PTR_ERR(motg->link_rst);
+// motg->link_rst = devm_reset_control_get(&pdev->dev, "link");
+// if (IS_ERR(motg->link_rst))
+// return PTR_ERR(motg->link_rst);
- motg->phy_rst = devm_reset_control_get(&pdev->dev, "phy");
- if (IS_ERR(motg->phy_rst))
- motg->phy_rst = NULL;
+// motg->phy_rst = devm_reset_control_get(&pdev->dev, "phy");
+// if (IS_ERR(motg->phy_rst))
+// motg->phy_rst = NULL;
pdata->mode = of_usb_get_dr_mode(node);
if (pdata->mode == USB_DR_MODE_UNKNOWN)
@@ -1539,8 +1599,10 @@ static int msm_otg_probe(struct platform_device *pdev)
if (!np)
return -ENXIO;
ret = msm_otg_read_dt(pdev, motg);
- if (ret)
+ if (ret) {
+ dev_err(&pdev->dev, "died in otg_read_dt: %d\n", ret);
return ret;
+ }
}
motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),