forked from Minki/linux
Revert "usb: dwc3: Don't switch OTG -> peripheral if extcon is present"
This reverts commit0f01017191
. As pointed out by Ferry this breaks Dual Role support on Intel Merrifield platforms. Fixes:0f01017191
("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 Reviewed-by: Sven Peter <sven@svenpeter.dev> Link: https://lore.kernel.org/r/20220927155332.10762-3-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
2adc960ce7
commit
7a84e7353e
@ -23,7 +23,6 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_graph.h>
|
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/pinctrl/consumer.h>
|
#include <linux/pinctrl/consumer.h>
|
||||||
#include <linux/reset.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
|
* mode. If the controller supports DRD but the dr_mode is not
|
||||||
* specified or set to OTG, then set the mode to peripheral.
|
* 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) ||
|
(!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) ||
|
||||||
!device_property_read_bool(dwc->dev, "usb-role-switch")) &&
|
!device_property_read_bool(dwc->dev, "usb-role-switch")) &&
|
||||||
!DWC3_VER_IS_PRIOR(DWC3, 330A))
|
!DWC3_VER_IS_PRIOR(DWC3, 330A))
|
||||||
@ -1691,51 +1690,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)
|
static int dwc3_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
@ -1886,13 +1840,6 @@ static int dwc3_probe(struct platform_device *pdev)
|
|||||||
goto err2;
|
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);
|
ret = dwc3_get_dr_mode(dwc);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err3;
|
goto err3;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/extcon.h>
|
#include <linux/extcon.h>
|
||||||
|
#include <linux/of_graph.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/property.h>
|
#include <linux/property.h>
|
||||||
@ -438,6 +439,51 @@ static int dwc3_drd_notifier(struct notifier_block *nb,
|
|||||||
return NOTIFY_DONE;
|
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)
|
#if IS_ENABLED(CONFIG_USB_ROLE_SWITCH)
|
||||||
#define ROLE_SWITCH 1
|
#define ROLE_SWITCH 1
|
||||||
static int dwc3_usb_role_switch_set(struct usb_role_switch *sw,
|
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"))
|
device_property_read_bool(dwc->dev, "usb-role-switch"))
|
||||||
return dwc3_setup_role_switch(dwc);
|
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) {
|
if (dwc->edev) {
|
||||||
dwc->edev_nb.notifier_call = dwc3_drd_notifier;
|
dwc->edev_nb.notifier_call = dwc3_drd_notifier;
|
||||||
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
|
ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
|
||||||
|
Loading…
Reference in New Issue
Block a user