diff --git a/drivers/usb/dwc3/dwc3-msm-core.c b/drivers/usb/dwc3/dwc3-msm-core.c index d26900bb9873..5475e58c937e 100644 --- a/drivers/usb/dwc3/dwc3-msm-core.c +++ b/drivers/usb/dwc3/dwc3-msm-core.c @@ -466,6 +466,7 @@ struct extcon_nb { int idx; struct notifier_block vbus_nb; struct notifier_block id_nb; + bool is_eud; }; /* Input bits to state machine (mdwc->inputs) */ @@ -4366,7 +4367,6 @@ static void dwc3_resume_work(struct work_struct *w) unsigned int extcon_id; struct extcon_dev *edev = NULL; const char *edev_name; - char *eud_str; int ret = 0; if (mdwc->dwc3) @@ -4386,8 +4386,7 @@ static void dwc3_resume_work(struct work_struct *w) edev_name = extcon_get_edev_name(edev); dbg_log_string("edev:%s\n", edev_name); /* Skip querying speed and cc_state for EUD edev */ - eud_str = strnstr(edev_name, "eud", strlen(edev_name)); - if (eud_str) + if (mdwc->extcon[mdwc->ext_idx].is_eud) goto skip_update; } @@ -4702,7 +4701,6 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb, struct extcon_dev *edev = ptr; struct extcon_nb *enb = container_of(nb, struct extcon_nb, vbus_nb); struct dwc3_msm *mdwc = enb->mdwc; - char *eud_str; const char *edev_name; if (!edev || !mdwc) @@ -4717,8 +4715,7 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb, dbg_log_string("edev:%s\n", edev_name); /* detect USB spoof disconnect/connect notification with EUD device */ - eud_str = strnstr(edev_name, "eud", strlen(edev_name)); - if (eud_str) { + if (mdwc->extcon[enb->idx].is_eud) { int spoof; spoof = extcon_get_state(edev, EXTCON_JIG); @@ -4752,12 +4749,34 @@ static int dwc3_msm_vbus_notifier(struct notifier_block *nb, return NOTIFY_DONE; } +static int dwc3_msm_extcon_is_valid_source(struct dwc3_msm *mdwc) +{ + struct device_node *node = mdwc->dev->of_node; + int idx; + int count; + + count = of_count_phandle_with_args(node, "extcon", NULL); + if (count < 0) { + dev_err(mdwc->dev, "of_count_phandle_with_args failed\n"); + return 0; + } + + for (idx = 0; idx < count; idx++) { + if (!mdwc->extcon[idx].is_eud) + return 1; + } + + return 0; +} + static int dwc3_msm_extcon_register(struct dwc3_msm *mdwc) { struct device_node *node = mdwc->dev->of_node; struct extcon_dev *edev; int idx, extcon_cnt, ret = 0; bool check_vbus_state, check_id_state, phandle_found = false; + char *eud_str; + const char *edev_name; extcon_cnt = of_count_phandle_with_args(node, "extcon", NULL); if (extcon_cnt < 0) { @@ -4785,6 +4804,11 @@ static int dwc3_msm_extcon_register(struct dwc3_msm *mdwc) mdwc->extcon[idx].edev = edev; mdwc->extcon[idx].idx = idx; + edev_name = extcon_get_edev_name(edev); + eud_str = strnstr(edev_name, "eud", strlen(edev_name)); + if (eud_str) + mdwc->extcon[idx].is_eud = true; + mdwc->extcon[idx].vbus_nb.notifier_call = dwc3_msm_vbus_notifier; ret = extcon_register_notifier(edev, EXTCON_USB, @@ -5897,7 +5921,8 @@ static int dwc3_msm_probe(struct platform_device *pdev) } } - if (!mdwc->role_switch && !mdwc->extcon) { + if (!mdwc->role_switch && (!mdwc->extcon || + !dwc3_msm_extcon_is_valid_source(mdwc))) { switch (mdwc->dr_mode) { case USB_DR_MODE_OTG: if (of_property_read_bool(node,