diff options
Diffstat (limited to 'drivers/usb/dwc3/dwc3-msm.c')
| -rw-r--r-- | drivers/usb/dwc3/dwc3-msm.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 0f4fb9012171..0650f0b69de7 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -66,6 +66,9 @@ /* AHB2PHY read/write waite value */ #define ONE_READ_WRITE_WAIT 0x11 +/* DP_DM linestate float */ +#define DP_DM_STATE_FLOAT 0x02 + /* cpu to fix usb interrupt */ static int cpu_to_affin; module_param(cpu_to_affin, int, S_IRUGO|S_IWUSR); @@ -249,6 +252,8 @@ struct dwc3_msm { bool hc_died; bool xhci_ss_compliance_enable; bool no_wakeup_src_in_hostmode; + bool check_for_float; + bool float_detected; struct extcon_dev *extcon_vbus; struct extcon_dev *extcon_id; @@ -2759,6 +2764,7 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb, if (mdwc->vbus_active == event) return NOTIFY_DONE; + mdwc->float_detected = false; cc_state = extcon_get_cable_state_(edev, EXTCON_USB_CC); if (cc_state < 0) mdwc->typec_orientation = ORIENTATION_NONE; @@ -3307,6 +3313,8 @@ static int dwc3_msm_probe(struct platform_device *pdev) if (of_property_read_bool(node, "qcom,disable-dev-mode-pm")) pm_runtime_get_noresume(mdwc->dev); + mdwc->check_for_float = of_property_read_bool(node, + "qcom,check-for-float"); ret = dwc3_msm_extcon_register(mdwc); if (ret) goto put_dwc3; @@ -3861,7 +3869,8 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) int ret, psy_type; psy_type = get_psy_type(mdwc); - if (psy_type == POWER_SUPPLY_TYPE_USB_FLOAT) { + if (psy_type == POWER_SUPPLY_TYPE_USB_FLOAT + || (mdwc->check_for_float && mdwc->float_detected)) { if (!mA) pval.intval = -ETIMEDOUT; else @@ -3952,6 +3961,7 @@ static void dwc3_otg_sm_work(struct work_struct *w) work = 1; } else if (test_bit(B_SESS_VLD, &mdwc->inputs)) { dev_dbg(mdwc->dev, "b_sess_vld\n"); + mdwc->float_detected = false; if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_FLOAT) queue_delayed_work(mdwc->dwc3_wq, &mdwc->sdp_check, @@ -3964,6 +3974,21 @@ static void dwc3_otg_sm_work(struct work_struct *w) pm_runtime_get_sync(mdwc->dev); dbg_event(0xFF, "BIDLE gsync", atomic_read(&mdwc->dev->power.usage_count)); + if (mdwc->check_for_float) { + /* + * If DP_DM are found to be floating, do not + * start the peripheral mode. + */ + if (usb_phy_dpdm_with_idp_src(mdwc->hs_phy) == + DP_DM_STATE_FLOAT) { + mdwc->float_detected = true; + dwc3_msm_gadget_vbus_draw(mdwc, 0); + pm_runtime_put_sync(mdwc->dev); + dbg_event(0xFF, "FLT sync", atomic_read( + &mdwc->dev->power.usage_count)); + break; + } + } dwc3_otg_start_peripheral(mdwc, 1); mdwc->drd_state = DRD_STATE_PERIPHERAL; work = 1; |
