On Tue, Sep 27, 2022 at 8:53 AM Andy Shevchenko andriy.shevchenko@linux.intel.com wrote:
This reverts commit 0f01017191384e3962fa31520a9fd9846c3d352f.
As pointed out by Ferry this breaks Dual Role support on Intel Merrifield platforms.
Fixes: 0f0101719138 ("usb: dwc3: Don't switch OTG -> peripheral if extcon is present") Reported-by: Ferry Toth fntoth@gmail.com Cc: stable@vger.kernel.org Signed-off-by: Andy Shevchenko andriy.shevchenko@linux.intel.com Tested-by: Ferry Toth fntoth@gmail.com # for Merrifield
Sven can you check that this also fixes the regression of your fix?
drivers/usb/dwc3/core.c | 55 +---------------------------------------- drivers/usb/dwc3/drd.c | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 54 deletions(-)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c2b463469d51..219d797e2230 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -23,7 +23,6 @@ #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/of.h> -#include <linux/of_graph.h> #include <linux/acpi.h> #include <linux/pinctrl/consumer.h> #include <linux/reset.h> @@ -86,7 +85,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) * mode. If the controller supports DRD but the dr_mode is not * specified or set to OTG, then set the mode to peripheral. */
if (mode == USB_DR_MODE_OTG && !dwc->edev &&
if (mode == USB_DR_MODE_OTG && (!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) || !device_property_read_bool(dwc->dev, "usb-role-switch")) && !DWC3_VER_IS_PRIOR(DWC3, 330A))@@ -1668,51 +1667,6 @@ static void dwc3_check_params(struct dwc3 *dwc) } }
-static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) -{
struct device *dev = dwc->dev;struct device_node *np_phy;struct extcon_dev *edev = NULL;const char *name;if (device_property_read_bool(dev, "extcon"))return extcon_get_edev_by_phandle(dev, 0);/** Device tree platforms should get extcon via phandle.* On ACPI platforms, we get the name from a device property.* This device property is for kernel internal use only and* is expected to be set by the glue code.*/if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {edev = extcon_get_extcon_dev(name);if (!edev)return ERR_PTR(-EPROBE_DEFER);return edev;}/** Try to get an extcon device from the USB PHY controller's "port"* node. Check if it has the "port" node first, to avoid printing the* error message from underlying code, as it's a valid case: extcon* device (and "port" node) may be missing in case of "usb-role-switch"* or OTG mode.*/np_phy = of_parse_phandle(dev->of_node, "phys", 0);if (of_graph_is_present(np_phy)) {struct device_node *np_conn;np_conn = of_graph_get_remote_node(np_phy, -1, -1);if (np_conn)edev = extcon_find_edev_by_node(np_conn);of_node_put(np_conn);}of_node_put(np_phy);return edev;-}
static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1849,13 +1803,6 @@ static int dwc3_probe(struct platform_device *pdev) goto err2; }
dwc->edev = dwc3_get_extcon(dwc);if (IS_ERR(dwc->edev)) {ret = PTR_ERR(dwc->edev);dev_err_probe(dwc->dev, ret, "failed to get extcon\n");goto err3;}ret = dwc3_get_dr_mode(dwc); if (ret) goto err3;diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index 039bf241769a..8cad9e7d3368 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c @@ -8,6 +8,7 @@ */
#include <linux/extcon.h> +#include <linux/of_graph.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/property.h> @@ -438,6 +439,51 @@ static int dwc3_drd_notifier(struct notifier_block *nb, return NOTIFY_DONE; }
+static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) +{
struct device *dev = dwc->dev;struct device_node *np_phy;struct extcon_dev *edev = NULL;const char *name;if (device_property_read_bool(dev, "extcon"))return extcon_get_edev_by_phandle(dev, 0);/** Device tree platforms should get extcon via phandle.* On ACPI platforms, we get the name from a device property.* This device property is for kernel internal use only and* is expected to be set by the glue code.*/if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {edev = extcon_get_extcon_dev(name);if (!edev)return ERR_PTR(-EPROBE_DEFER);return edev;}/** Try to get an extcon device from the USB PHY controller's "port"* node. Check if it has the "port" node first, to avoid printing the* error message from underlying code, as it's a valid case: extcon* device (and "port" node) may be missing in case of "usb-role-switch"* or OTG mode.*/np_phy = of_parse_phandle(dev->of_node, "phys", 0);if (of_graph_is_present(np_phy)) {struct device_node *np_conn;np_conn = of_graph_get_remote_node(np_phy, -1, -1);if (np_conn)edev = extcon_find_edev_by_node(np_conn);of_node_put(np_conn);}of_node_put(np_phy);return edev;+}
#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH) #define ROLE_SWITCH 1 static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, @@ -542,6 +588,10 @@ int dwc3_drd_init(struct dwc3 *dwc) device_property_read_bool(dwc->dev, "usb-role-switch")) return dwc3_setup_role_switch(dwc);
dwc->edev = dwc3_get_extcon(dwc);if (IS_ERR(dwc->edev))return PTR_ERR(dwc->edev);if (dwc->edev) { dwc->edev_nb.notifier_call = dwc3_drd_notifier; ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,-- 2.35.1