Loading Documentation/devicetree/bindings/usb/msm-phy.txt +1 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,7 @@ Optional properties: "tune2_efuse_addr": EFUSE based register address to read TUNE2 parameter. via the QSCRATCH interface. "emu_phy_base" : phy base address used for programming emulation target phy. "ref_clk_addr" : ref_clk bcr address used for on/off ref_clk before reset. - reg-names: Should be "qscratch_base". The qscratch register bank allows us to manipulate QUSB PHY bits eg. to enable D+ pull-up using s/w control in device mode. The reg-names property is required if the Loading arch/arm/boot/dts/qcom/msm8996.dtsi +10 −6 Original line number Diff line number Diff line Loading @@ -1917,10 +1917,12 @@ compatible = "qcom,qusb2phy"; reg = <0x07411000 0x180>, <0x06af8800 0x400>, <0x0007024C 0x4>; <0x0007024c 0x4>, <0x00388018 0x4>; reg-names = "qusb_phy_base", "qscratch_base", "tune2_efuse_addr"; "tune2_efuse_addr", "ref_clk_addr"; vdd-supply = <&pm8994_s2_corner>; vdda18-supply = <&pm8994_l12>; vdda33-supply = <&pm8994_l24>; Loading Loading @@ -1953,10 +1955,12 @@ compatible = "qcom,qusb2phy"; reg = <0x07412000 0x180>, <0x076f8800 0x400>, <0x0007024C 0x4>; <0x0007024c 0x4>, <0x00388014 0x4>; reg-names = "qusb_phy_base", "qscratch_base", "tune2_efuse_addr"; "tune2_efuse_addr", "ref_clk_addr"; vdd-supply = <&pm8994_s2_corner>; vdda18-supply = <&pm8994_l12>; vdda33-supply = <&pm8994_l24>; Loading Loading @@ -1988,8 +1992,8 @@ ssphy: ssphy@7410000 { compatible = "qcom,usb-ssphy-qmp-v2"; reg = <0x7410000 0x45C>, <0x007AB244 0x4>; reg = <0x7410000 0x45c>, <0x007ab244 0x4>; reg-names = "qmp_phy_base", "vls_clamp_reg"; vdd-supply = <&pm8994_l28>; Loading drivers/usb/dwc3/dwc3-msm.c +0 −14 Original line number Diff line number Diff line Loading @@ -1508,20 +1508,6 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) dev_dbg(mdwc->dev, "%s: exit power collapse (POR=%d)\n", __func__, mdwc->power_collapse_por); /* Reset HSPHY */ ret = usb_phy_reset(mdwc->hs_phy); if (ret) { dev_err(mdwc->dev, "hsphy reset failed\n"); return ret; } /* Reset SS PHY */ ret = usb_phy_reset(mdwc->ss_phy); if (ret) { dev_err(mdwc->dev, "ssphy reset failed\n"); return ret; } if (mdwc->power_collapse_por) dwc3_msm_power_collapse_por(mdwc); Loading drivers/usb/phy/phy-msm-qusb.c +60 −14 Original line number Diff line number Diff line Loading @@ -25,6 +25,9 @@ #include <linux/usb/phy.h> #include <linux/usb/msm_hsusb.h> #define QUSB2PHY_PLL_STATUS 0x38 #define QUSB2PHY_PLL_LOCK BIT(5) #define QUSB2PHY_PORT_QC1 0x70 #define VDM_SRC_EN BIT(4) #define VDP_SRC_EN BIT(2) Loading Loading @@ -84,6 +87,8 @@ #define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */ #define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */ #define QUSB2PHY_REFCLK_ENABLE BIT(0) unsigned int tune2; module_param(tune2, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(tune2, "QUSB PHY TUNE2"); Loading @@ -93,6 +98,7 @@ struct qusb_phy { void __iomem *base; void __iomem *qscratch_base; void __iomem *tune2_efuse_reg; void __iomem *ref_clk_base; struct clk *ref_clk_src; struct clk *ref_clk; Loading Loading @@ -128,19 +134,6 @@ struct qusb_phy { int emu_dcm_reset_seq_len; }; static int qusb_phy_reset(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); dev_dbg(phy->dev, "%s\n", __func__); clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); usleep_range(100, 150); clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); return 0; } static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on) { dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d on:%d\n", Loading Loading @@ -531,6 +524,28 @@ static int qusb_phy_init(struct usb_phy *phy) qusb_phy_enable_clocks(qphy, true); /* * ref clock is enabled by default after power on reset. Linux clock * driver will disable this clock as part of late init if peripheral * driver(s) does not explicitly votes for it. Linux clock driver also * does not disable the clock until late init even if peripheral * driver explicitly requests it and cannot defer the probe until late * init. Hence, Explicitly disable the clock using register write to * allow QUSB PHY PLL to lock properly. */ if (qphy->ref_clk_base) { writel_relaxed((readl_relaxed(qphy->ref_clk_base) & ~QUSB2PHY_REFCLK_ENABLE), qphy->ref_clk_base); /* Make sure that above write complete to get ref clk OFF */ wmb(); } /* Perform phy reset */ clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); usleep_range(100, 150); clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); if (qphy->emulation) { if (qphy->emu_init_seq) qusb_phy_write_seq(qphy->emu_phy_base, Loading Loading @@ -596,6 +611,29 @@ static int qusb_phy_init(struct usb_phy *phy) /* Enable the PHY */ writel_relaxed(CLAMP_N_EN | FREEZIO_N, qphy->base + QUSB2PHY_PORT_POWERDOWN); /* Ensure above write is completed before turning ON ref clk */ wmb(); /* Require to get phy pll lock successfully */ usleep_range(150, 160); if (!(readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS) & QUSB2PHY_PLL_LOCK)) { dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS)); WARN_ON(1); } /* Turn on phy ref_clk */ if (qphy->ref_clk_base) { writel_relaxed((readl_relaxed(qphy->ref_clk_base) | QUSB2PHY_REFCLK_ENABLE), qphy->ref_clk_base); /* Make sure that above write is completed to get ref clk ON */ wmb(); } return 0; } Loading Loading @@ -826,6 +864,15 @@ static int qusb_phy_probe(struct platform_device *pdev) } } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ref_clk_addr"); if (res) { qphy->ref_clk_base = devm_ioremap_nocache(dev, res->start, resource_size(res)); if (IS_ERR(qphy->ref_clk_base)) dev_dbg(dev, "ref_clk_address is not available.\n"); } qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src"); if (IS_ERR(qphy->ref_clk_src)) return PTR_ERR(qphy->ref_clk_src); Loading Loading @@ -974,7 +1021,6 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.init = qusb_phy_init; qphy->phy.set_suspend = qusb_phy_set_suspend; qphy->phy.shutdown = qusb_phy_shutdown; qphy->phy.reset = qusb_phy_reset; qphy->phy.change_dpdm = qusb_phy_update_dpdm; qphy->phy.type = USB_PHY_TYPE_USB2; Loading Loading
Documentation/devicetree/bindings/usb/msm-phy.txt +1 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,7 @@ Optional properties: "tune2_efuse_addr": EFUSE based register address to read TUNE2 parameter. via the QSCRATCH interface. "emu_phy_base" : phy base address used for programming emulation target phy. "ref_clk_addr" : ref_clk bcr address used for on/off ref_clk before reset. - reg-names: Should be "qscratch_base". The qscratch register bank allows us to manipulate QUSB PHY bits eg. to enable D+ pull-up using s/w control in device mode. The reg-names property is required if the Loading
arch/arm/boot/dts/qcom/msm8996.dtsi +10 −6 Original line number Diff line number Diff line Loading @@ -1917,10 +1917,12 @@ compatible = "qcom,qusb2phy"; reg = <0x07411000 0x180>, <0x06af8800 0x400>, <0x0007024C 0x4>; <0x0007024c 0x4>, <0x00388018 0x4>; reg-names = "qusb_phy_base", "qscratch_base", "tune2_efuse_addr"; "tune2_efuse_addr", "ref_clk_addr"; vdd-supply = <&pm8994_s2_corner>; vdda18-supply = <&pm8994_l12>; vdda33-supply = <&pm8994_l24>; Loading Loading @@ -1953,10 +1955,12 @@ compatible = "qcom,qusb2phy"; reg = <0x07412000 0x180>, <0x076f8800 0x400>, <0x0007024C 0x4>; <0x0007024c 0x4>, <0x00388014 0x4>; reg-names = "qusb_phy_base", "qscratch_base", "tune2_efuse_addr"; "tune2_efuse_addr", "ref_clk_addr"; vdd-supply = <&pm8994_s2_corner>; vdda18-supply = <&pm8994_l12>; vdda33-supply = <&pm8994_l24>; Loading Loading @@ -1988,8 +1992,8 @@ ssphy: ssphy@7410000 { compatible = "qcom,usb-ssphy-qmp-v2"; reg = <0x7410000 0x45C>, <0x007AB244 0x4>; reg = <0x7410000 0x45c>, <0x007ab244 0x4>; reg-names = "qmp_phy_base", "vls_clamp_reg"; vdd-supply = <&pm8994_l28>; Loading
drivers/usb/dwc3/dwc3-msm.c +0 −14 Original line number Diff line number Diff line Loading @@ -1508,20 +1508,6 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) dev_dbg(mdwc->dev, "%s: exit power collapse (POR=%d)\n", __func__, mdwc->power_collapse_por); /* Reset HSPHY */ ret = usb_phy_reset(mdwc->hs_phy); if (ret) { dev_err(mdwc->dev, "hsphy reset failed\n"); return ret; } /* Reset SS PHY */ ret = usb_phy_reset(mdwc->ss_phy); if (ret) { dev_err(mdwc->dev, "ssphy reset failed\n"); return ret; } if (mdwc->power_collapse_por) dwc3_msm_power_collapse_por(mdwc); Loading
drivers/usb/phy/phy-msm-qusb.c +60 −14 Original line number Diff line number Diff line Loading @@ -25,6 +25,9 @@ #include <linux/usb/phy.h> #include <linux/usb/msm_hsusb.h> #define QUSB2PHY_PLL_STATUS 0x38 #define QUSB2PHY_PLL_LOCK BIT(5) #define QUSB2PHY_PORT_QC1 0x70 #define VDM_SRC_EN BIT(4) #define VDP_SRC_EN BIT(2) Loading Loading @@ -84,6 +87,8 @@ #define QUSB2PHY_3P3_VOL_MAX 3200000 /* uV */ #define QUSB2PHY_3P3_HPM_LOAD 30000 /* uA */ #define QUSB2PHY_REFCLK_ENABLE BIT(0) unsigned int tune2; module_param(tune2, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(tune2, "QUSB PHY TUNE2"); Loading @@ -93,6 +98,7 @@ struct qusb_phy { void __iomem *base; void __iomem *qscratch_base; void __iomem *tune2_efuse_reg; void __iomem *ref_clk_base; struct clk *ref_clk_src; struct clk *ref_clk; Loading Loading @@ -128,19 +134,6 @@ struct qusb_phy { int emu_dcm_reset_seq_len; }; static int qusb_phy_reset(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); dev_dbg(phy->dev, "%s\n", __func__); clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); usleep_range(100, 150); clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); return 0; } static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on) { dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d on:%d\n", Loading Loading @@ -531,6 +524,28 @@ static int qusb_phy_init(struct usb_phy *phy) qusb_phy_enable_clocks(qphy, true); /* * ref clock is enabled by default after power on reset. Linux clock * driver will disable this clock as part of late init if peripheral * driver(s) does not explicitly votes for it. Linux clock driver also * does not disable the clock until late init even if peripheral * driver explicitly requests it and cannot defer the probe until late * init. Hence, Explicitly disable the clock using register write to * allow QUSB PHY PLL to lock properly. */ if (qphy->ref_clk_base) { writel_relaxed((readl_relaxed(qphy->ref_clk_base) & ~QUSB2PHY_REFCLK_ENABLE), qphy->ref_clk_base); /* Make sure that above write complete to get ref clk OFF */ wmb(); } /* Perform phy reset */ clk_reset(qphy->phy_reset, CLK_RESET_ASSERT); usleep_range(100, 150); clk_reset(qphy->phy_reset, CLK_RESET_DEASSERT); if (qphy->emulation) { if (qphy->emu_init_seq) qusb_phy_write_seq(qphy->emu_phy_base, Loading Loading @@ -596,6 +611,29 @@ static int qusb_phy_init(struct usb_phy *phy) /* Enable the PHY */ writel_relaxed(CLAMP_N_EN | FREEZIO_N, qphy->base + QUSB2PHY_PORT_POWERDOWN); /* Ensure above write is completed before turning ON ref clk */ wmb(); /* Require to get phy pll lock successfully */ usleep_range(150, 160); if (!(readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS) & QUSB2PHY_PLL_LOCK)) { dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", readb_relaxed(qphy->base + QUSB2PHY_PLL_STATUS)); WARN_ON(1); } /* Turn on phy ref_clk */ if (qphy->ref_clk_base) { writel_relaxed((readl_relaxed(qphy->ref_clk_base) | QUSB2PHY_REFCLK_ENABLE), qphy->ref_clk_base); /* Make sure that above write is completed to get ref clk ON */ wmb(); } return 0; } Loading Loading @@ -826,6 +864,15 @@ static int qusb_phy_probe(struct platform_device *pdev) } } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ref_clk_addr"); if (res) { qphy->ref_clk_base = devm_ioremap_nocache(dev, res->start, resource_size(res)); if (IS_ERR(qphy->ref_clk_base)) dev_dbg(dev, "ref_clk_address is not available.\n"); } qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src"); if (IS_ERR(qphy->ref_clk_src)) return PTR_ERR(qphy->ref_clk_src); Loading Loading @@ -974,7 +1021,6 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.init = qusb_phy_init; qphy->phy.set_suspend = qusb_phy_set_suspend; qphy->phy.shutdown = qusb_phy_shutdown; qphy->phy.reset = qusb_phy_reset; qphy->phy.change_dpdm = qusb_phy_update_dpdm; qphy->phy.type = USB_PHY_TYPE_USB2; Loading