usb: dwc3: dwc3-msm-core: Check for valid EXTCON connection source

During DWC3 MSM probe, if extcon and usb role switch are both undefined,
the mode will be set to peripheral.  However, in case EUD is defined, then
the extcon parameter will be non-null, and the probe routine will avoid
setting the default mode into peripheral, even though there is no valid
source for notifying cable events.

In case of when EUD is registered as the EXTCON device, continue to allow
setting the default mode as peripheral mode, as it does not send cable
events to DWC3 MSM.  This is useful bringup scenarios where UCSI role
switch is not ready, but EUD is enabled.

Change-Id: I82263a125f67560558236356ddc733301c586de3
Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
This commit is contained in:
Wesley Cheng 2022-11-24 01:44:19 -08:00
parent 88f0bf1775
commit ff382ccda5

View File

@ -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,