Loading Documentation/devicetree/bindings/usb/msm-phy.txt +2 −0 Original line number Diff line number Diff line Loading @@ -176,6 +176,8 @@ Optional properties: - qcom,hold-reset: Indicates that hold QUSB PHY into reset state. - qcom,phy-clk-scheme: Should be one of "cml" or "cmos" if ref_clk_addr is provided. - qcom,major-rev: provide major revision number to differentiate power up sequence. default is 2.0 - pinctrl-names/pinctrl-0/1: The GPIOs configured as output function. Names represents "active" state when attached in host mode and "suspend" state when detached. Example: qusb_phy: qusb@f9b39000 { Loading drivers/usb/phy/phy-msm-qusb-v2.c +68 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/usb/phy.h> #include <linux/reset.h> #include <linux/debugfs.h> #include <linux/hrtimer.h> /* QUSB2PHY_PWR_CTRL1 register related bits */ #define PWR_CTRL1_POWR_DOWN BIT(0) Loading Loading @@ -126,6 +127,10 @@ struct qusb_phy { u32 sq_ctrl2_default; bool chirp_disable; struct pinctrl *pinctrl; struct pinctrl_state *atest_usb13_suspend; struct pinctrl_state *atest_usb13_active; /* emulation targets specific */ void __iomem *emu_phy_base; bool emulation; Loading @@ -139,6 +144,8 @@ struct qusb_phy { /* override TUNEX registers value */ struct dentry *root; u8 tune[5]; struct hrtimer timer; }; static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on) Loading Loading @@ -511,6 +518,42 @@ static int qusb_phy_init(struct usb_phy *phy) return 0; } static enum hrtimer_restart qusb_dis_ext_pulldown_timer(struct hrtimer *timer) { struct qusb_phy *qphy = container_of(timer, struct qusb_phy, timer); int ret = 0; if (qphy->pinctrl && qphy->atest_usb13_suspend) { ret = pinctrl_select_state(qphy->pinctrl, qphy->atest_usb13_suspend); if (ret < 0) dev_err(qphy->phy.dev, "pinctrl state suspend select failed\n"); } return HRTIMER_NORESTART; } static void qusb_phy_enable_ext_pulldown(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); int ret = 0; dev_dbg(phy->dev, "%s\n", __func__); if (qphy->pinctrl && qphy->atest_usb13_active) { ret = pinctrl_select_state(qphy->pinctrl, qphy->atest_usb13_active); if (ret < 0) { dev_err(phy->dev, "pinctrl state active select failed\n"); return; } hrtimer_start(&qphy->timer, ms_to_ktime(10), HRTIMER_MODE_REL); } } static void qusb_phy_shutdown(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); Loading Loading @@ -1082,6 +1125,30 @@ static int qusb_phy_probe(struct platform_device *pdev) return PTR_ERR(qphy->vdda18); } qphy->pinctrl = devm_pinctrl_get(dev); if (IS_ERR(qphy->pinctrl)) { ret = PTR_ERR(qphy->pinctrl); if (ret == -EPROBE_DEFER) return ret; dev_err(dev, "pinctrl not available\n"); goto skip_pinctrl_config; } qphy->atest_usb13_suspend = pinctrl_lookup_state(qphy->pinctrl, "atest_usb13_suspend"); if (IS_ERR(qphy->atest_usb13_suspend)) { dev_err(dev, "pinctrl lookup atest_usb13_suspend failed\n"); goto skip_pinctrl_config; } qphy->atest_usb13_active = pinctrl_lookup_state(qphy->pinctrl, "atest_usb13_active"); if (IS_ERR(qphy->atest_usb13_active)) dev_err(dev, "pinctrl lookup atest_usb13_active failed\n"); hrtimer_init(&qphy->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); qphy->timer.function = qusb_dis_ext_pulldown_timer; skip_pinctrl_config: mutex_init(&qphy->lock); platform_set_drvdata(pdev, qphy); Loading @@ -1093,6 +1160,7 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.notify_connect = qusb_phy_notify_connect; qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; qphy->phy.disable_chirp = qusb_phy_disable_chirp; qphy->phy.start_port_reset = qusb_phy_enable_ext_pulldown; ret = usb_add_phy_dev(&qphy->phy); if (ret) Loading include/linux/usb/phy.h +11 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,8 @@ struct usb_phy { /* enable/disable VBUS */ int (*set_vbus)(struct usb_phy *x, int on); /* callback to indicate port is being reset or reset the port */ void (*start_port_reset)(struct usb_phy *x); /* effective for B devices, ignored for A-peripheral */ int (*set_power)(struct usb_phy *x, Loading Loading @@ -213,6 +215,15 @@ usb_phy_vbus_off(struct usb_phy *x) return x->set_vbus(x, false); } static inline void usb_phy_start_port_reset(struct usb_phy *x) { if (!x || !x->start_port_reset) return; x->start_port_reset(x); } static inline int usb_phy_reset(struct usb_phy *x) { Loading Loading
Documentation/devicetree/bindings/usb/msm-phy.txt +2 −0 Original line number Diff line number Diff line Loading @@ -176,6 +176,8 @@ Optional properties: - qcom,hold-reset: Indicates that hold QUSB PHY into reset state. - qcom,phy-clk-scheme: Should be one of "cml" or "cmos" if ref_clk_addr is provided. - qcom,major-rev: provide major revision number to differentiate power up sequence. default is 2.0 - pinctrl-names/pinctrl-0/1: The GPIOs configured as output function. Names represents "active" state when attached in host mode and "suspend" state when detached. Example: qusb_phy: qusb@f9b39000 { Loading
drivers/usb/phy/phy-msm-qusb-v2.c +68 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/usb/phy.h> #include <linux/reset.h> #include <linux/debugfs.h> #include <linux/hrtimer.h> /* QUSB2PHY_PWR_CTRL1 register related bits */ #define PWR_CTRL1_POWR_DOWN BIT(0) Loading Loading @@ -126,6 +127,10 @@ struct qusb_phy { u32 sq_ctrl2_default; bool chirp_disable; struct pinctrl *pinctrl; struct pinctrl_state *atest_usb13_suspend; struct pinctrl_state *atest_usb13_active; /* emulation targets specific */ void __iomem *emu_phy_base; bool emulation; Loading @@ -139,6 +144,8 @@ struct qusb_phy { /* override TUNEX registers value */ struct dentry *root; u8 tune[5]; struct hrtimer timer; }; static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on) Loading Loading @@ -511,6 +518,42 @@ static int qusb_phy_init(struct usb_phy *phy) return 0; } static enum hrtimer_restart qusb_dis_ext_pulldown_timer(struct hrtimer *timer) { struct qusb_phy *qphy = container_of(timer, struct qusb_phy, timer); int ret = 0; if (qphy->pinctrl && qphy->atest_usb13_suspend) { ret = pinctrl_select_state(qphy->pinctrl, qphy->atest_usb13_suspend); if (ret < 0) dev_err(qphy->phy.dev, "pinctrl state suspend select failed\n"); } return HRTIMER_NORESTART; } static void qusb_phy_enable_ext_pulldown(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); int ret = 0; dev_dbg(phy->dev, "%s\n", __func__); if (qphy->pinctrl && qphy->atest_usb13_active) { ret = pinctrl_select_state(qphy->pinctrl, qphy->atest_usb13_active); if (ret < 0) { dev_err(phy->dev, "pinctrl state active select failed\n"); return; } hrtimer_start(&qphy->timer, ms_to_ktime(10), HRTIMER_MODE_REL); } } static void qusb_phy_shutdown(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); Loading Loading @@ -1082,6 +1125,30 @@ static int qusb_phy_probe(struct platform_device *pdev) return PTR_ERR(qphy->vdda18); } qphy->pinctrl = devm_pinctrl_get(dev); if (IS_ERR(qphy->pinctrl)) { ret = PTR_ERR(qphy->pinctrl); if (ret == -EPROBE_DEFER) return ret; dev_err(dev, "pinctrl not available\n"); goto skip_pinctrl_config; } qphy->atest_usb13_suspend = pinctrl_lookup_state(qphy->pinctrl, "atest_usb13_suspend"); if (IS_ERR(qphy->atest_usb13_suspend)) { dev_err(dev, "pinctrl lookup atest_usb13_suspend failed\n"); goto skip_pinctrl_config; } qphy->atest_usb13_active = pinctrl_lookup_state(qphy->pinctrl, "atest_usb13_active"); if (IS_ERR(qphy->atest_usb13_active)) dev_err(dev, "pinctrl lookup atest_usb13_active failed\n"); hrtimer_init(&qphy->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); qphy->timer.function = qusb_dis_ext_pulldown_timer; skip_pinctrl_config: mutex_init(&qphy->lock); platform_set_drvdata(pdev, qphy); Loading @@ -1093,6 +1160,7 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.notify_connect = qusb_phy_notify_connect; qphy->phy.notify_disconnect = qusb_phy_notify_disconnect; qphy->phy.disable_chirp = qusb_phy_disable_chirp; qphy->phy.start_port_reset = qusb_phy_enable_ext_pulldown; ret = usb_add_phy_dev(&qphy->phy); if (ret) Loading
include/linux/usb/phy.h +11 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,8 @@ struct usb_phy { /* enable/disable VBUS */ int (*set_vbus)(struct usb_phy *x, int on); /* callback to indicate port is being reset or reset the port */ void (*start_port_reset)(struct usb_phy *x); /* effective for B devices, ignored for A-peripheral */ int (*set_power)(struct usb_phy *x, Loading Loading @@ -213,6 +215,15 @@ usb_phy_vbus_off(struct usb_phy *x) return x->set_vbus(x, false); } static inline void usb_phy_start_port_reset(struct usb_phy *x) { if (!x || !x->start_port_reset) return; x->start_port_reset(x); } static inline int usb_phy_reset(struct usb_phy *x) { Loading