Loading Documentation/devicetree/bindings/usb/msm-ssusb.txt +3 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,9 @@ Optional properties : - qcom,disable-host-mode-pm: If present, it disables XHCI PM runtime functionality when USB host mode is used. - qcom,core-clk-rate: If present, indicates clock frequency to be set for USB master clock. - qcom,detect-dpdm-floating: Indicates if SDP must be rechecked for floating data lines. If datalines are floating then don't treat that as SDP. Sub nodes: - Sub node for "DWC3- USB3 controller". This sub node is required property for device node. The properties of this subnode Loading drivers/usb/dwc3/dwc3-msm.c +43 −8 Original line number Diff line number Diff line Loading @@ -157,8 +157,6 @@ enum dwc3_id_state { * DWC3_PROPRIETARY_CHARGER A non-standard charger that pulls DP/DM to * specific voltages between 2.0-3.3v for * identification. * DWC3_FLOATED_CHARGER Non standard charger whose data lines are * floating. */ enum dwc3_chg_type { DWC3_INVALID_CHARGER = 0, Loading @@ -166,7 +164,6 @@ enum dwc3_chg_type { DWC3_DCP_CHARGER, DWC3_CDP_CHARGER, DWC3_PROPRIETARY_CHARGER, DWC3_FLOATED_CHARGER, }; struct dwc3_msm { Loading Loading @@ -208,10 +205,10 @@ struct dwc3_msm { enum dwc3_chg_type chg_type; unsigned max_power; bool charging_disabled; bool detect_dpdm_floating; enum usb_otg_state otg_state; enum usb_chg_state chg_state; int pmic_id_irq; u8 dcd_retries; struct work_struct bus_vote_w; unsigned int bus_vote; u32 bus_perf_client; Loading Loading @@ -1817,7 +1814,6 @@ static const char *chg_to_string(enum dwc3_chg_type chg_type) case DWC3_DCP_CHARGER: return "USB_DCP_CHARGER"; case DWC3_CDP_CHARGER: return "USB_CDP_CHARGER"; case DWC3_PROPRIETARY_CHARGER: return "USB_PROPRIETARY_CHARGER"; case DWC3_FLOATED_CHARGER: return "USB_FLOATED_CHARGER"; default: return "UNKNOWN_CHARGER"; } } Loading Loading @@ -1853,7 +1849,8 @@ static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc) unsigned long timeout; u32 reg = 0; if ((mdwc->in_host_mode || mdwc->vbus_active) if ((mdwc->in_host_mode || (mdwc->vbus_active && mdwc->otg_state == OTG_STATE_B_SUSPEND)) && dwc3_msm_is_superspeed(mdwc)) { if (!atomic_read(&mdwc->in_p3)) { dev_err(mdwc->dev, "Not in P3,aborting LPM sequence\n"); Loading Loading @@ -2003,7 +2000,9 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) clk_disable_unprepare(mdwc->xo_clk); /* Perform controller power collapse */ if (!mdwc->in_host_mode && (!mdwc->vbus_active || mdwc->in_restart)) { if (!mdwc->in_host_mode && (!mdwc->vbus_active || mdwc->otg_state == OTG_STATE_B_IDLE || mdwc->in_restart)) { mdwc->lpm_flags |= MDWC3_POWER_COLLAPSE; dev_dbg(mdwc->dev, "%s: power collapse\n", __func__); dwc3_msm_config_gdsc(mdwc, 0); Loading Loading @@ -2036,7 +2035,8 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) * using HS_PHY_IRQ or SS_PHY_IRQ. Hence enable wakeup only in * case of host bus suspend and device bus suspend. */ if (mdwc->vbus_active || mdwc->in_host_mode) { if ((mdwc->vbus_active && mdwc->otg_state == OTG_STATE_B_SUSPEND) || mdwc->in_host_mode) { enable_irq_wake(mdwc->hs_phy_irq); enable_irq(mdwc->hs_phy_irq); if (mdwc->ss_phy_irq) { Loading Loading @@ -2918,6 +2918,9 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->disable_host_mode_pm = of_property_read_bool(node, "qcom,disable-host-mode-pm"); mdwc->detect_dpdm_floating = of_property_read_bool(node, "qcom,detect-dpdm-floating"); dwc3_set_notifier(&dwc3_msm_notify_event); /* Assumes dwc3 is the only DT child of dwc3-msm */ Loading Loading @@ -3373,6 +3376,26 @@ psy_error: return -ENXIO; } static void dwc3_check_float_lines(struct dwc3_msm *mdwc) { int dpdm; dev_dbg(mdwc->dev, "%s: Check linestate\n", __func__); dwc3_msm_gadget_vbus_draw(mdwc, 0); /* Get linestate with Idp_src enabled */ dpdm = usb_phy_dpdm_with_idp_src(mdwc->hs_phy); if (dpdm == 0x2) { /* DP is HIGH = lines are floating */ mdwc->chg_type = DWC3_PROPRIETARY_CHARGER; mdwc->otg_state = OTG_STATE_B_IDLE; pm_runtime_put_sync(mdwc->dev); dbg_event(0xFF, "FLT psync", atomic_read(&mdwc->dev->power.usage_count)); } else if (dpdm) { dev_dbg(mdwc->dev, "%s:invalid linestate:%x\n", __func__, dpdm); } } static void dwc3_initialize(struct dwc3_msm *mdwc) { Loading Loading @@ -3492,6 +3515,12 @@ static void dwc3_otg_sm_work(struct work_struct *w) pm_runtime_enable(mdwc->dev); pm_runtime_get_noresume(mdwc->dev); dwc3_initialize(mdwc); /* check dp/dm for SDP & runtime_put if !SDP */ if (mdwc->detect_dpdm_floating) { dwc3_check_float_lines(mdwc); if (mdwc->chg_type != DWC3_SDP_CHARGER) break; } dwc3_otg_start_peripheral(mdwc, 1); mdwc->otg_state = OTG_STATE_B_PERIPHERAL; dbg_event(0xFF, "Undef SDP", Loading Loading @@ -3548,6 +3577,12 @@ static void dwc3_otg_sm_work(struct work_struct *w) dbg_event(0xFF, "CHG gsync", atomic_read( &mdwc->dev->power.usage_count)); /* check dp/dm for SDP & runtime_put if !SDP */ if (mdwc->detect_dpdm_floating) { dwc3_check_float_lines(mdwc); if (mdwc->chg_type != DWC3_SDP_CHARGER) break; } dwc3_otg_start_peripheral(mdwc, 1); mdwc->otg_state = OTG_STATE_B_PERIPHERAL; work = 1; Loading drivers/usb/phy/phy-msm-qusb.c +96 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,23 @@ /* TCSR_PHY_CLK_SCHEME_SEL bit mask */ #define PHY_CLK_SCHEME_SEL BIT(0) #define QUSB2PHY_PLL_PWR_CTL 0x18 #define REF_BUF_EN BIT(0) #define REXT_EN BIT(1) #define PLL_BYPASSNL BIT(2) #define REXT_TRIM_0 BIT(4) #define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1C #define PLL_RESET_N_CNT_5 0x5 #define PLL_RESET_N BIT(4) #define PLL_AUTOPGM_EN BIT(7) #define QUSB2PHY_PORT_QUICKCHARGE1 0x70 #define IDP_SRC_EN BIT(3) #define QUSB2PHY_PORT_QUICKCHARGE2 0x74 #define QUSB2PHY_PORT_INT_STATUS 0xF0 #define QUSB2PHY_PLL_STATUS 0x38 #define QUSB2PHY_PLL_LOCK BIT(5) Loading @@ -47,6 +64,7 @@ #define POWER_DOWN BIT(0) #define QUSB2PHY_PORT_UTMI_CTRL1 0xC0 #define SUSPEND_N BIT(5) #define TERM_SELECT BIT(4) #define XCVR_SELECT_FS BIT(2) #define OP_MODE_NON_DRIVE BIT(0) Loading Loading @@ -730,6 +748,83 @@ static void qusb_phy_shutdown(struct usb_phy *phy) qusb_phy_enable_clocks(qphy, false); } /** * Returns DP/DM linestate with Idp_src enabled to detect if lines are floating * * @uphy - usb phy pointer. * */ static int qusb_phy_linestate_with_idp_src(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); u8 int_status, ret; /* Disable/powerdown the PHY */ writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, qphy->base + QUSB2PHY_PORT_POWERDOWN); /* Put PHY in non-driving mode */ writel_relaxed(TERM_SELECT | XCVR_SELECT_FS | OP_MODE_NON_DRIVE | SUSPEND_N, qphy->base + QUSB2PHY_PORT_UTMI_CTRL1); /* Switch PHY to utmi register mode */ writel_relaxed(UTMI_ULPI_SEL | UTMI_TEST_MUX_SEL, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); writel_relaxed(PLL_RESET_N_CNT_5, qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); /* Enable PHY */ writel_relaxed(CLAMP_N_EN | FREEZIO_N, qphy->base + QUSB2PHY_PORT_POWERDOWN); writel_relaxed(REF_BUF_EN | REXT_EN | PLL_BYPASSNL | REXT_TRIM_0, qphy->base + QUSB2PHY_PLL_PWR_CTL); usleep_range(5, 1000); writel_relaxed(PLL_RESET_N | PLL_RESET_N_CNT_5, qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); usleep_range(50, 1000); writel_relaxed(0x00, qphy->base + QUSB2PHY_PORT_QUICKCHARGE1); writel_relaxed(0x00, qphy->base + QUSB2PHY_PORT_QUICKCHARGE2); /* Enable all chg_det events from PHY */ writel_relaxed(0x1F, qphy->base + QUSB2PHY_PORT_INTR_CTRL); /* Enable Idp_src */ writel_relaxed(IDP_SRC_EN, qphy->base + QUSB2PHY_PORT_QUICKCHARGE1); usleep_range(1000, 2000); int_status = readl_relaxed(qphy->base + QUSB2PHY_PORT_INT_STATUS); /* Exit chg_det mode, set PHY regs to default values */ writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, qphy->base + QUSB2PHY_PORT_POWERDOWN); /* 23 */ writel_relaxed(PLL_AUTOPGM_EN | PLL_RESET_N | PLL_RESET_N_CNT_5, qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); writel_relaxed(UTMI_ULPI_SEL, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); writel_relaxed(TERM_SELECT, qphy->base + QUSB2PHY_PORT_UTMI_CTRL1); writel_relaxed(CLAMP_N_EN | FREEZIO_N, qphy->base + QUSB2PHY_PORT_POWERDOWN); int_status = int_status & 0x5; /* * int_status's Bit(0) is DP and Bit(2) is DM. * Caller expects bit(1) as DP and bit(0) DM i.e. usual linestate format */ ret = (int_status >> 2) | ((int_status & 0x1) << 1); pr_debug("%s: int_status:%x, dpdm:%x\n", __func__, int_status, ret); return ret; } /** * Performs QUSB2 PHY suspend/resume functionality. * Loading Loading @@ -1121,6 +1216,7 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.shutdown = qusb_phy_shutdown; qphy->phy.change_dpdm = qusb_phy_update_dpdm; qphy->phy.type = USB_PHY_TYPE_USB2; qphy->phy.dpdm_with_idp_src = qusb_phy_linestate_with_idp_src; if (qphy->qscratch_base) { qphy->phy.notify_connect = qusb_phy_notify_connect; Loading include/linux/usb/phy.h +10 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,8 @@ struct usb_phy { char *event, int msg1, int msg2); /* update DP/DM state */ int (*change_dpdm)(struct usb_phy *x, int dpdm); /* return linestate with Idp_src (used for DCD with USB2 PHY) */ int (*dpdm_with_idp_src)(struct usb_phy *x); }; /** Loading Loading @@ -334,6 +336,14 @@ usb_phy_dbg_events(struct usb_phy *x, x->dbg_event(x, event, msg1, msg2); } static inline int usb_phy_dpdm_with_idp_src(struct usb_phy *x) { if (x && x->dpdm_with_idp_src) return x->dpdm_with_idp_src(x); return 0; } /* notifiers */ static inline int usb_register_notifier(struct usb_phy *x, struct notifier_block *nb) Loading Loading
Documentation/devicetree/bindings/usb/msm-ssusb.txt +3 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,9 @@ Optional properties : - qcom,disable-host-mode-pm: If present, it disables XHCI PM runtime functionality when USB host mode is used. - qcom,core-clk-rate: If present, indicates clock frequency to be set for USB master clock. - qcom,detect-dpdm-floating: Indicates if SDP must be rechecked for floating data lines. If datalines are floating then don't treat that as SDP. Sub nodes: - Sub node for "DWC3- USB3 controller". This sub node is required property for device node. The properties of this subnode Loading
drivers/usb/dwc3/dwc3-msm.c +43 −8 Original line number Diff line number Diff line Loading @@ -157,8 +157,6 @@ enum dwc3_id_state { * DWC3_PROPRIETARY_CHARGER A non-standard charger that pulls DP/DM to * specific voltages between 2.0-3.3v for * identification. * DWC3_FLOATED_CHARGER Non standard charger whose data lines are * floating. */ enum dwc3_chg_type { DWC3_INVALID_CHARGER = 0, Loading @@ -166,7 +164,6 @@ enum dwc3_chg_type { DWC3_DCP_CHARGER, DWC3_CDP_CHARGER, DWC3_PROPRIETARY_CHARGER, DWC3_FLOATED_CHARGER, }; struct dwc3_msm { Loading Loading @@ -208,10 +205,10 @@ struct dwc3_msm { enum dwc3_chg_type chg_type; unsigned max_power; bool charging_disabled; bool detect_dpdm_floating; enum usb_otg_state otg_state; enum usb_chg_state chg_state; int pmic_id_irq; u8 dcd_retries; struct work_struct bus_vote_w; unsigned int bus_vote; u32 bus_perf_client; Loading Loading @@ -1817,7 +1814,6 @@ static const char *chg_to_string(enum dwc3_chg_type chg_type) case DWC3_DCP_CHARGER: return "USB_DCP_CHARGER"; case DWC3_CDP_CHARGER: return "USB_CDP_CHARGER"; case DWC3_PROPRIETARY_CHARGER: return "USB_PROPRIETARY_CHARGER"; case DWC3_FLOATED_CHARGER: return "USB_FLOATED_CHARGER"; default: return "UNKNOWN_CHARGER"; } } Loading Loading @@ -1853,7 +1849,8 @@ static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc) unsigned long timeout; u32 reg = 0; if ((mdwc->in_host_mode || mdwc->vbus_active) if ((mdwc->in_host_mode || (mdwc->vbus_active && mdwc->otg_state == OTG_STATE_B_SUSPEND)) && dwc3_msm_is_superspeed(mdwc)) { if (!atomic_read(&mdwc->in_p3)) { dev_err(mdwc->dev, "Not in P3,aborting LPM sequence\n"); Loading Loading @@ -2003,7 +2000,9 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) clk_disable_unprepare(mdwc->xo_clk); /* Perform controller power collapse */ if (!mdwc->in_host_mode && (!mdwc->vbus_active || mdwc->in_restart)) { if (!mdwc->in_host_mode && (!mdwc->vbus_active || mdwc->otg_state == OTG_STATE_B_IDLE || mdwc->in_restart)) { mdwc->lpm_flags |= MDWC3_POWER_COLLAPSE; dev_dbg(mdwc->dev, "%s: power collapse\n", __func__); dwc3_msm_config_gdsc(mdwc, 0); Loading Loading @@ -2036,7 +2035,8 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) * using HS_PHY_IRQ or SS_PHY_IRQ. Hence enable wakeup only in * case of host bus suspend and device bus suspend. */ if (mdwc->vbus_active || mdwc->in_host_mode) { if ((mdwc->vbus_active && mdwc->otg_state == OTG_STATE_B_SUSPEND) || mdwc->in_host_mode) { enable_irq_wake(mdwc->hs_phy_irq); enable_irq(mdwc->hs_phy_irq); if (mdwc->ss_phy_irq) { Loading Loading @@ -2918,6 +2918,9 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->disable_host_mode_pm = of_property_read_bool(node, "qcom,disable-host-mode-pm"); mdwc->detect_dpdm_floating = of_property_read_bool(node, "qcom,detect-dpdm-floating"); dwc3_set_notifier(&dwc3_msm_notify_event); /* Assumes dwc3 is the only DT child of dwc3-msm */ Loading Loading @@ -3373,6 +3376,26 @@ psy_error: return -ENXIO; } static void dwc3_check_float_lines(struct dwc3_msm *mdwc) { int dpdm; dev_dbg(mdwc->dev, "%s: Check linestate\n", __func__); dwc3_msm_gadget_vbus_draw(mdwc, 0); /* Get linestate with Idp_src enabled */ dpdm = usb_phy_dpdm_with_idp_src(mdwc->hs_phy); if (dpdm == 0x2) { /* DP is HIGH = lines are floating */ mdwc->chg_type = DWC3_PROPRIETARY_CHARGER; mdwc->otg_state = OTG_STATE_B_IDLE; pm_runtime_put_sync(mdwc->dev); dbg_event(0xFF, "FLT psync", atomic_read(&mdwc->dev->power.usage_count)); } else if (dpdm) { dev_dbg(mdwc->dev, "%s:invalid linestate:%x\n", __func__, dpdm); } } static void dwc3_initialize(struct dwc3_msm *mdwc) { Loading Loading @@ -3492,6 +3515,12 @@ static void dwc3_otg_sm_work(struct work_struct *w) pm_runtime_enable(mdwc->dev); pm_runtime_get_noresume(mdwc->dev); dwc3_initialize(mdwc); /* check dp/dm for SDP & runtime_put if !SDP */ if (mdwc->detect_dpdm_floating) { dwc3_check_float_lines(mdwc); if (mdwc->chg_type != DWC3_SDP_CHARGER) break; } dwc3_otg_start_peripheral(mdwc, 1); mdwc->otg_state = OTG_STATE_B_PERIPHERAL; dbg_event(0xFF, "Undef SDP", Loading Loading @@ -3548,6 +3577,12 @@ static void dwc3_otg_sm_work(struct work_struct *w) dbg_event(0xFF, "CHG gsync", atomic_read( &mdwc->dev->power.usage_count)); /* check dp/dm for SDP & runtime_put if !SDP */ if (mdwc->detect_dpdm_floating) { dwc3_check_float_lines(mdwc); if (mdwc->chg_type != DWC3_SDP_CHARGER) break; } dwc3_otg_start_peripheral(mdwc, 1); mdwc->otg_state = OTG_STATE_B_PERIPHERAL; work = 1; Loading
drivers/usb/phy/phy-msm-qusb.c +96 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,23 @@ /* TCSR_PHY_CLK_SCHEME_SEL bit mask */ #define PHY_CLK_SCHEME_SEL BIT(0) #define QUSB2PHY_PLL_PWR_CTL 0x18 #define REF_BUF_EN BIT(0) #define REXT_EN BIT(1) #define PLL_BYPASSNL BIT(2) #define REXT_TRIM_0 BIT(4) #define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1C #define PLL_RESET_N_CNT_5 0x5 #define PLL_RESET_N BIT(4) #define PLL_AUTOPGM_EN BIT(7) #define QUSB2PHY_PORT_QUICKCHARGE1 0x70 #define IDP_SRC_EN BIT(3) #define QUSB2PHY_PORT_QUICKCHARGE2 0x74 #define QUSB2PHY_PORT_INT_STATUS 0xF0 #define QUSB2PHY_PLL_STATUS 0x38 #define QUSB2PHY_PLL_LOCK BIT(5) Loading @@ -47,6 +64,7 @@ #define POWER_DOWN BIT(0) #define QUSB2PHY_PORT_UTMI_CTRL1 0xC0 #define SUSPEND_N BIT(5) #define TERM_SELECT BIT(4) #define XCVR_SELECT_FS BIT(2) #define OP_MODE_NON_DRIVE BIT(0) Loading Loading @@ -730,6 +748,83 @@ static void qusb_phy_shutdown(struct usb_phy *phy) qusb_phy_enable_clocks(qphy, false); } /** * Returns DP/DM linestate with Idp_src enabled to detect if lines are floating * * @uphy - usb phy pointer. * */ static int qusb_phy_linestate_with_idp_src(struct usb_phy *phy) { struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy); u8 int_status, ret; /* Disable/powerdown the PHY */ writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, qphy->base + QUSB2PHY_PORT_POWERDOWN); /* Put PHY in non-driving mode */ writel_relaxed(TERM_SELECT | XCVR_SELECT_FS | OP_MODE_NON_DRIVE | SUSPEND_N, qphy->base + QUSB2PHY_PORT_UTMI_CTRL1); /* Switch PHY to utmi register mode */ writel_relaxed(UTMI_ULPI_SEL | UTMI_TEST_MUX_SEL, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); writel_relaxed(PLL_RESET_N_CNT_5, qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); /* Enable PHY */ writel_relaxed(CLAMP_N_EN | FREEZIO_N, qphy->base + QUSB2PHY_PORT_POWERDOWN); writel_relaxed(REF_BUF_EN | REXT_EN | PLL_BYPASSNL | REXT_TRIM_0, qphy->base + QUSB2PHY_PLL_PWR_CTL); usleep_range(5, 1000); writel_relaxed(PLL_RESET_N | PLL_RESET_N_CNT_5, qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); usleep_range(50, 1000); writel_relaxed(0x00, qphy->base + QUSB2PHY_PORT_QUICKCHARGE1); writel_relaxed(0x00, qphy->base + QUSB2PHY_PORT_QUICKCHARGE2); /* Enable all chg_det events from PHY */ writel_relaxed(0x1F, qphy->base + QUSB2PHY_PORT_INTR_CTRL); /* Enable Idp_src */ writel_relaxed(IDP_SRC_EN, qphy->base + QUSB2PHY_PORT_QUICKCHARGE1); usleep_range(1000, 2000); int_status = readl_relaxed(qphy->base + QUSB2PHY_PORT_INT_STATUS); /* Exit chg_det mode, set PHY regs to default values */ writel_relaxed(CLAMP_N_EN | FREEZIO_N | POWER_DOWN, qphy->base + QUSB2PHY_PORT_POWERDOWN); /* 23 */ writel_relaxed(PLL_AUTOPGM_EN | PLL_RESET_N | PLL_RESET_N_CNT_5, qphy->base + QUSB2PHY_PLL_AUTOPGM_CTL1); writel_relaxed(UTMI_ULPI_SEL, qphy->base + QUSB2PHY_PORT_UTMI_CTRL2); writel_relaxed(TERM_SELECT, qphy->base + QUSB2PHY_PORT_UTMI_CTRL1); writel_relaxed(CLAMP_N_EN | FREEZIO_N, qphy->base + QUSB2PHY_PORT_POWERDOWN); int_status = int_status & 0x5; /* * int_status's Bit(0) is DP and Bit(2) is DM. * Caller expects bit(1) as DP and bit(0) DM i.e. usual linestate format */ ret = (int_status >> 2) | ((int_status & 0x1) << 1); pr_debug("%s: int_status:%x, dpdm:%x\n", __func__, int_status, ret); return ret; } /** * Performs QUSB2 PHY suspend/resume functionality. * Loading Loading @@ -1121,6 +1216,7 @@ static int qusb_phy_probe(struct platform_device *pdev) qphy->phy.shutdown = qusb_phy_shutdown; qphy->phy.change_dpdm = qusb_phy_update_dpdm; qphy->phy.type = USB_PHY_TYPE_USB2; qphy->phy.dpdm_with_idp_src = qusb_phy_linestate_with_idp_src; if (qphy->qscratch_base) { qphy->phy.notify_connect = qusb_phy_notify_connect; Loading
include/linux/usb/phy.h +10 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,8 @@ struct usb_phy { char *event, int msg1, int msg2); /* update DP/DM state */ int (*change_dpdm)(struct usb_phy *x, int dpdm); /* return linestate with Idp_src (used for DCD with USB2 PHY) */ int (*dpdm_with_idp_src)(struct usb_phy *x); }; /** Loading Loading @@ -334,6 +336,14 @@ usb_phy_dbg_events(struct usb_phy *x, x->dbg_event(x, event, msg1, msg2); } static inline int usb_phy_dpdm_with_idp_src(struct usb_phy *x) { if (x && x->dpdm_with_idp_src) return x->dpdm_with_idp_src(x); return 0; } /* notifiers */ static inline int usb_register_notifier(struct usb_phy *x, struct notifier_block *nb) Loading