Skip to content

Commit d182c2e

Browse files
ndreysgregkh
authored andcommitted
usb: dwc3: Don't switch OTG -> peripheral if extcon is present
If the extcon device exists, get the mode from the extcon device. If the controller is DRD and the driver is unable to determine the mode, only then default the dr_mode to USB_DR_MODE_PERIPHERAL. Reported-by: Steev Klimaszewski <[email protected]> Fixes: 7a84e73 ("Revert "usb: dwc3: Don't switch OTG -> peripheral if extcon is present"") Cc: stable <[email protected]> Reviewed-by: Thinh Nguyen <[email protected]> Signed-off-by: Andrey Smirnov <[email protected]> Signed-off-by: Andy Shevchenko <[email protected]> Tested-by: Steev Klimaszewski <[email protected]> Acked-by: Thinh Nguyen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 593c5ba commit d182c2e

File tree

2 files changed

+48
-51
lines changed

2 files changed

+48
-51
lines changed

drivers/usb/dwc3/core.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <linux/delay.h>
2424
#include <linux/dma-mapping.h>
2525
#include <linux/of.h>
26+
#include <linux/of_graph.h>
2627
#include <linux/acpi.h>
2728
#include <linux/pinctrl/consumer.h>
2829
#include <linux/reset.h>
@@ -85,7 +86,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
8586
* mode. If the controller supports DRD but the dr_mode is not
8687
* specified or set to OTG, then set the mode to peripheral.
8788
*/
88-
if (mode == USB_DR_MODE_OTG &&
89+
if (mode == USB_DR_MODE_OTG && !dwc->edev &&
8990
(!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) ||
9091
!device_property_read_bool(dwc->dev, "usb-role-switch")) &&
9192
!DWC3_VER_IS_PRIOR(DWC3, 330A))
@@ -1690,6 +1691,46 @@ static void dwc3_check_params(struct dwc3 *dwc)
16901691
}
16911692
}
16921693

1694+
static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
1695+
{
1696+
struct device *dev = dwc->dev;
1697+
struct device_node *np_phy;
1698+
struct extcon_dev *edev = NULL;
1699+
const char *name;
1700+
1701+
if (device_property_read_bool(dev, "extcon"))
1702+
return extcon_get_edev_by_phandle(dev, 0);
1703+
1704+
/*
1705+
* Device tree platforms should get extcon via phandle.
1706+
* On ACPI platforms, we get the name from a device property.
1707+
* This device property is for kernel internal use only and
1708+
* is expected to be set by the glue code.
1709+
*/
1710+
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0)
1711+
return extcon_get_extcon_dev(name);
1712+
1713+
/*
1714+
* Try to get an extcon device from the USB PHY controller's "port"
1715+
* node. Check if it has the "port" node first, to avoid printing the
1716+
* error message from underlying code, as it's a valid case: extcon
1717+
* device (and "port" node) may be missing in case of "usb-role-switch"
1718+
* or OTG mode.
1719+
*/
1720+
np_phy = of_parse_phandle(dev->of_node, "phys", 0);
1721+
if (of_graph_is_present(np_phy)) {
1722+
struct device_node *np_conn;
1723+
1724+
np_conn = of_graph_get_remote_node(np_phy, -1, -1);
1725+
if (np_conn)
1726+
edev = extcon_find_edev_by_node(np_conn);
1727+
of_node_put(np_conn);
1728+
}
1729+
of_node_put(np_phy);
1730+
1731+
return edev;
1732+
}
1733+
16931734
static int dwc3_probe(struct platform_device *pdev)
16941735
{
16951736
struct device *dev = &pdev->dev;
@@ -1840,6 +1881,12 @@ static int dwc3_probe(struct platform_device *pdev)
18401881
goto err2;
18411882
}
18421883

1884+
dwc->edev = dwc3_get_extcon(dwc);
1885+
if (IS_ERR(dwc->edev)) {
1886+
ret = dev_err_probe(dwc->dev, PTR_ERR(dwc->edev), "failed to get extcon\n");
1887+
goto err3;
1888+
}
1889+
18431890
ret = dwc3_get_dr_mode(dwc);
18441891
if (ret)
18451892
goto err3;

drivers/usb/dwc3/drd.c

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
*/
99

1010
#include <linux/extcon.h>
11-
#include <linux/of_graph.h>
1211
#include <linux/of_platform.h>
1312
#include <linux/platform_device.h>
1413
#include <linux/property.h>
@@ -439,51 +438,6 @@ static int dwc3_drd_notifier(struct notifier_block *nb,
439438
return NOTIFY_DONE;
440439
}
441440

442-
static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
443-
{
444-
struct device *dev = dwc->dev;
445-
struct device_node *np_phy;
446-
struct extcon_dev *edev = NULL;
447-
const char *name;
448-
449-
if (device_property_read_bool(dev, "extcon"))
450-
return extcon_get_edev_by_phandle(dev, 0);
451-
452-
/*
453-
* Device tree platforms should get extcon via phandle.
454-
* On ACPI platforms, we get the name from a device property.
455-
* This device property is for kernel internal use only and
456-
* is expected to be set by the glue code.
457-
*/
458-
if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {
459-
edev = extcon_get_extcon_dev(name);
460-
if (!edev)
461-
return ERR_PTR(-EPROBE_DEFER);
462-
463-
return edev;
464-
}
465-
466-
/*
467-
* Try to get an extcon device from the USB PHY controller's "port"
468-
* node. Check if it has the "port" node first, to avoid printing the
469-
* error message from underlying code, as it's a valid case: extcon
470-
* device (and "port" node) may be missing in case of "usb-role-switch"
471-
* or OTG mode.
472-
*/
473-
np_phy = of_parse_phandle(dev->of_node, "phys", 0);
474-
if (of_graph_is_present(np_phy)) {
475-
struct device_node *np_conn;
476-
477-
np_conn = of_graph_get_remote_node(np_phy, -1, -1);
478-
if (np_conn)
479-
edev = extcon_find_edev_by_node(np_conn);
480-
of_node_put(np_conn);
481-
}
482-
of_node_put(np_phy);
483-
484-
return edev;
485-
}
486-
487441
#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH)
488442
#define ROLE_SWITCH 1
489443
static int dwc3_usb_role_switch_set(struct usb_role_switch *sw,
@@ -588,10 +542,6 @@ int dwc3_drd_init(struct dwc3 *dwc)
588542
device_property_read_bool(dwc->dev, "usb-role-switch"))
589543
return dwc3_setup_role_switch(dwc);
590544

591-
dwc->edev = dwc3_get_extcon(dwc);
592-
if (IS_ERR(dwc->edev))
593-
return PTR_ERR(dwc->edev);
594-
595545
if (dwc->edev) {
596546
dwc->edev_nb.notifier_call = dwc3_drd_notifier;
597547
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,

0 commit comments

Comments
 (0)