|
|
|
@ -7,8 +7,8 @@ Signed-off-by: Andy Gross <agross@codeaurora.org> |
|
|
|
|
---
|
|
|
|
|
drivers/phy/Kconfig | 12 +
|
|
|
|
|
drivers/phy/Makefile | 1 +
|
|
|
|
|
drivers/phy/phy-qcom-dwc3.c | 546 ++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
3 files changed, 559 insertions(+)
|
|
|
|
|
drivers/phy/phy-qcom-dwc3.c | 575 ++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
|
3 files changed, 588 insertions(+)
|
|
|
|
|
create mode 100644 drivers/phy/phy-qcom-dwc3.c
|
|
|
|
|
|
|
|
|
|
--- a/drivers/phy/Kconfig
|
|
|
|
@ -39,7 +39,7 @@ Signed-off-by: Andy Gross <agross@codeaurora.org> |
|
|
|
|
+obj-$(CONFIG_PHY_QCOM_DWC3) += phy-qcom-dwc3.o
|
|
|
|
|
--- /dev/null
|
|
|
|
|
+++ b/drivers/phy/phy-qcom-dwc3.c
|
|
|
|
|
@@ -0,0 +1,546 @@
|
|
|
|
|
@@ -0,0 +1,575 @@
|
|
|
|
|
+/* Copyright (c) 2014-2015, Code Aurora Forum. All rights reserved.
|
|
|
|
|
+ *
|
|
|
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
|
|
@ -299,36 +299,21 @@ Signed-off-by: Andy Gross <agross@codeaurora.org> |
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int qcom_dwc3_phy_power_on(struct phy *phy)
|
|
|
|
|
+static int qcom_dwc3_hs_phy_init(struct phy *phy)
|
|
|
|
|
+{
|
|
|
|
|
+ int ret;
|
|
|
|
|
+ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy);
|
|
|
|
|
+ int ret;
|
|
|
|
|
+ u32 val;
|
|
|
|
|
+
|
|
|
|
|
+ ret = clk_prepare_enable(phy_dwc3->xo_clk);
|
|
|
|
|
+ if (ret)
|
|
|
|
|
+ return ret;
|
|
|
|
|
+
|
|
|
|
|
+ ret = clk_prepare_enable(phy_dwc3->ref_clk);
|
|
|
|
|
+ if (ret)
|
|
|
|
|
+ if (ret) {
|
|
|
|
|
+ clk_disable_unprepare(phy_dwc3->xo_clk);
|
|
|
|
|
+
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int qcom_dwc3_phy_power_off(struct phy *phy)
|
|
|
|
|
+{
|
|
|
|
|
+ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy);
|
|
|
|
|
+
|
|
|
|
|
+ clk_disable_unprepare(phy_dwc3->ref_clk);
|
|
|
|
|
+ clk_disable_unprepare(phy_dwc3->xo_clk);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int qcom_dwc3_hs_phy_init(struct phy *phy)
|
|
|
|
|
+{
|
|
|
|
|
+ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy);
|
|
|
|
|
+ u32 val;
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * HSPHY Initialization: Enable UTMI clock, select 19.2MHz fsel
|
|
|
|
@ -353,12 +338,32 @@ Signed-off-by: Andy Gross <agross@codeaurora.org> |
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int qcom_dwc3_hs_phy_exit(struct phy *phy)
|
|
|
|
|
+{
|
|
|
|
|
+ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy);
|
|
|
|
|
+
|
|
|
|
|
+ clk_disable_unprepare(phy_dwc3->ref_clk);
|
|
|
|
|
+ clk_disable_unprepare(phy_dwc3->xo_clk);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int qcom_dwc3_ss_phy_init(struct phy *phy)
|
|
|
|
|
+{
|
|
|
|
|
+ struct qcom_dwc3_usb_phy *phy_dwc3 = phy_get_drvdata(phy);
|
|
|
|
|
+ int ret;
|
|
|
|
|
+ u32 data = 0;
|
|
|
|
|
+
|
|
|
|
|
+ ret = clk_prepare_enable(phy_dwc3->xo_clk);
|
|
|
|
|
+ if (ret)
|
|
|
|
|
+ return ret;
|
|
|
|
|
+
|
|
|
|
|
+ ret = clk_prepare_enable(phy_dwc3->ref_clk);
|
|
|
|
|
+ if (ret) {
|
|
|
|
|
+ clk_disable_unprepare(phy_dwc3->xo_clk);
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* reset phy */
|
|
|
|
|
+ data = readl(phy_dwc3->base + SSUSB_PHY_CTRL_REG);
|
|
|
|
|
+ writel(data | SSUSB_CTRL_SS_PHY_RESET,
|
|
|
|
@ -381,6 +386,30 @@ Signed-off-by: Andy Gross <agross@codeaurora.org> |
|
|
|
|
+ writel(data, phy_dwc3->base + SSUSB_PHY_CTRL_REG);
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * WORKAROUND: There is SSPHY suspend bug due to which USB enumerates
|
|
|
|
|
+ * in HS mode instead of SS mode. Workaround it by asserting
|
|
|
|
|
+ * LANE0.TX_ALT_BLOCK.EN_ALT_BUS to enable TX to use alt bus mode
|
|
|
|
|
+ */
|
|
|
|
|
+ ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, 0x102D, &data);
|
|
|
|
|
+ if (ret)
|
|
|
|
|
+ goto err_phy_trans;
|
|
|
|
|
+
|
|
|
|
|
+ data |= (1 << 7);
|
|
|
|
|
+ ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, 0x102D, data);
|
|
|
|
|
+ if (ret)
|
|
|
|
|
+ goto err_phy_trans;
|
|
|
|
|
+
|
|
|
|
|
+ ret = qcom_dwc3_ss_read_phycreg(phy_dwc3->base, 0x1010, &data);
|
|
|
|
|
+ if (ret)
|
|
|
|
|
+ goto err_phy_trans;
|
|
|
|
|
+
|
|
|
|
|
+ data &= ~0xff0;
|
|
|
|
|
+ data |= 0x20;
|
|
|
|
|
+ ret = qcom_dwc3_ss_write_phycreg(phy_dwc3, 0x1010, data);
|
|
|
|
|
+ if (ret)
|
|
|
|
|
+ goto err_phy_trans;
|
|
|
|
|
+
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Fix RX Equalization setting as follows
|
|
|
|
|
+ * LANE0.RX_OVRD_IN_HI. RX_EQ_EN set to 0
|
|
|
|
|
+ * LANE0.RX_OVRD_IN_HI.RX_EQ_EN_OVRD set to 1
|
|
|
|
@ -462,7 +491,10 @@ Signed-off-by: Andy Gross <agross@codeaurora.org> |
|
|
|
|
+ qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG,
|
|
|
|
|
+ SSUSB_CTRL_REF_USE_PAD, 0x0);
|
|
|
|
|
+ qcom_dwc3_phy_write_readback(phy_dwc3, SSUSB_PHY_CTRL_REG,
|
|
|
|
|
+ 0x0, SSUSB_CTRL_TEST_POWERDOWN);
|
|
|
|
|
+ SSUSB_CTRL_TEST_POWERDOWN, 0x0);
|
|
|
|
|
+
|
|
|
|
|
+ clk_disable_unprepare(phy_dwc3->ref_clk);
|
|
|
|
|
+ clk_disable_unprepare(phy_dwc3->xo_clk);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
@ -470,8 +502,7 @@ Signed-off-by: Andy Gross <agross@codeaurora.org> |
|
|
|
|
+static const struct qcom_dwc3_phy_drvdata qcom_dwc3_hs_drvdata = {
|
|
|
|
|
+ .ops = {
|
|
|
|
|
+ .init = qcom_dwc3_hs_phy_init,
|
|
|
|
|
+ .power_on = qcom_dwc3_phy_power_on,
|
|
|
|
|
+ .power_off = qcom_dwc3_phy_power_off,
|
|
|
|
|
+ .exit = qcom_dwc3_hs_phy_exit,
|
|
|
|
|
+ .owner = THIS_MODULE,
|
|
|
|
|
+ },
|
|
|
|
|
+ .clk_rate = 60000000,
|
|
|
|
@ -481,8 +512,6 @@ Signed-off-by: Andy Gross <agross@codeaurora.org> |
|
|
|
|
+ .ops = {
|
|
|
|
|
+ .init = qcom_dwc3_ss_phy_init,
|
|
|
|
|
+ .exit = qcom_dwc3_ss_phy_exit,
|
|
|
|
|
+ .power_on = qcom_dwc3_phy_power_on,
|
|
|
|
|
+ .power_off = qcom_dwc3_phy_power_off,
|
|
|
|
|
+ .owner = THIS_MODULE,
|
|
|
|
|
+ },
|
|
|
|
|
+ .clk_rate = 125000000,
|
|
|
|
|