diff options
author | Andy Green <andy.green@linaro.org> | 2014-12-19 13:28:22 +0800 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2014-12-26 18:43:09 +0800 |
commit | 8b301eb471b45aba1433dbcd9baeff86e603dbc3 (patch) | |
tree | 7d3530ab4e99d680b418ab4c1144ed392f0a915c | |
parent | 04cce957b708289e9ec293eaf2d0572ae6496f1e (diff) |
Signed-off-by: Andy Green <andy.green@linaro.org>
-rw-r--r-- | drivers/usb/phy/phy-msm-usb.c | 88 |
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), |