From: Pavel Kubelun Date: Thu, 15 Jun 2017 08:48:17 +0000 (+0300) Subject: ipq806x: dwc3: Fix power_on and power_off sequence X-Git-Tag: v18.06.0-rc1~1233 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6617f3c6ab00b456284a2c2704701e59e1d0ae15;p=oweals%2Fopenwrt.git ipq806x: dwc3: Fix power_on and power_off sequence Picking commit from QSDK https://source.codeaurora.org/quic/qsdk/oss/kernel/linux-msm/commit/drivers/phy/phy-qcom-dwc3.c?h=eggplant&id=d316437c9cdb70023a760342678f32e27241725a The commit fixes: - dwc3 phy module unloading - possibly fixes FS#177 when some devices were improperly enumerated as HS while being SS thus stucking the driver during boot. Signed-off-by: Pavel Kubelun --- diff --git a/target/linux/ipq806x/patches-4.9/0032-phy-add-qcom-dwc3-phy.patch b/target/linux/ipq806x/patches-4.9/0032-phy-add-qcom-dwc3-phy.patch index 230afd293c..bd777858e0 100644 --- a/target/linux/ipq806x/patches-4.9/0032-phy-add-qcom-dwc3-phy.patch +++ b/target/linux/ipq806x/patches-4.9/0032-phy-add-qcom-dwc3-phy.patch @@ -7,8 +7,8 @@ Signed-off-by: Andy Gross --- 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 +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 + 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 + 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 + 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 + 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 +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 + .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,