diff options
Diffstat (limited to 'drivers/usb/common/common.c')
| -rw-r--r-- | drivers/usb/common/common.c | 60 | 
1 files changed, 54 insertions, 6 deletions
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index 673d53038ed2..e6ec125e4485 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -17,6 +17,7 @@  #include <linux/usb/ch9.h>  #include <linux/usb/of.h>  #include <linux/usb/otg.h> +#include <linux/of_platform.h>  const char *usb_otg_state_string(enum usb_otg_state state)  { @@ -106,25 +107,72 @@ static const char *const usb_dr_modes[] = {  	[USB_DR_MODE_OTG]		= "otg",  }; +static enum usb_dr_mode usb_get_dr_mode_from_string(const char *str) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++) +		if (!strcmp(usb_dr_modes[i], str)) +			return i; + +	return USB_DR_MODE_UNKNOWN; +} +  enum usb_dr_mode usb_get_dr_mode(struct device *dev)  {  	const char *dr_mode; -	int err, i; +	int err;  	err = device_property_read_string(dev, "dr_mode", &dr_mode);  	if (err < 0)  		return USB_DR_MODE_UNKNOWN; -	for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++) -		if (!strcmp(dr_mode, usb_dr_modes[i])) -			return i; - -	return USB_DR_MODE_UNKNOWN; +	return usb_get_dr_mode_from_string(dr_mode);  }  EXPORT_SYMBOL_GPL(usb_get_dr_mode);  #ifdef CONFIG_OF  /** + * of_usb_get_dr_mode_by_phy - Get dual role mode for the controller device + * which is associated with the given phy device_node + * @np:	Pointer to the given phy device_node + * + * In dts a usb controller associates with phy devices.  The function gets + * the string from property 'dr_mode' of the controller associated with the + * given phy device node, and returns the correspondig enum usb_dr_mode. + */ +enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np) +{ +	struct device_node *controller = NULL; +	struct device_node *phy; +	const char *dr_mode; +	int index; +	int err; + +	do { +		controller = of_find_node_with_property(controller, "phys"); +		index = 0; +		do { +			phy = of_parse_phandle(controller, "phys", index); +			of_node_put(phy); +			if (phy == phy_np) +				goto finish; +			index++; +		} while (phy); +	} while (controller); + +finish: +	err = of_property_read_string(controller, "dr_mode", &dr_mode); +	of_node_put(controller); + +	if (err < 0) +		return USB_DR_MODE_UNKNOWN; + +	return usb_get_dr_mode_from_string(dr_mode); +} +EXPORT_SYMBOL_GPL(of_usb_get_dr_mode_by_phy); + +/**   * of_usb_host_tpl_support - to get if Targeted Peripheral List is supported   * for given targeted hosts (non-PC hosts)   * @np: Pointer to the given device_node  | 
