Commit 98bfb394 authored by Bin Liu's avatar Bin Liu Committed by Felipe Balbi

usb: of: add an api to get dr_mode by the phy node

Some USB phy drivers have different handling for the controller in each
dr_mode. But the phy driver does not have visibility to the dr_mode of
the controller.

This adds an api to return the dr_mode of the controller which
associates the given phy node.
Signed-off-by: default avatarBin Liu <b-liu@ti.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent fa4dce20
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <linux/usb/of.h> #include <linux/usb/of.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/of_platform.h>
const char *usb_otg_state_string(enum usb_otg_state state) const char *usb_otg_state_string(enum usb_otg_state state)
{ {
...@@ -106,24 +107,71 @@ static const char *const usb_dr_modes[] = { ...@@ -106,24 +107,71 @@ static const char *const usb_dr_modes[] = {
[USB_DR_MODE_OTG] = "otg", [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) enum usb_dr_mode usb_get_dr_mode(struct device *dev)
{ {
const char *dr_mode; const char *dr_mode;
int err, i; int err;
err = device_property_read_string(dev, "dr_mode", &dr_mode); err = device_property_read_string(dev, "dr_mode", &dr_mode);
if (err < 0) if (err < 0)
return USB_DR_MODE_UNKNOWN; return USB_DR_MODE_UNKNOWN;
for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++) return usb_get_dr_mode_from_string(dr_mode);
if (!strcmp(dr_mode, usb_dr_modes[i]))
return i;
return USB_DR_MODE_UNKNOWN;
} }
EXPORT_SYMBOL_GPL(usb_get_dr_mode); EXPORT_SYMBOL_GPL(usb_get_dr_mode);
#ifdef CONFIG_OF #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 * of_usb_host_tpl_support - to get if Targeted Peripheral List is supported
* for given targeted hosts (non-PC hosts) * for given targeted hosts (non-PC hosts)
......
...@@ -12,10 +12,15 @@ ...@@ -12,10 +12,15 @@
#include <linux/usb/phy.h> #include <linux/usb/phy.h>
#if IS_ENABLED(CONFIG_OF) #if IS_ENABLED(CONFIG_OF)
enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np);
bool of_usb_host_tpl_support(struct device_node *np); bool of_usb_host_tpl_support(struct device_node *np);
int of_usb_update_otg_caps(struct device_node *np, int of_usb_update_otg_caps(struct device_node *np,
struct usb_otg_caps *otg_caps); struct usb_otg_caps *otg_caps);
#else #else
enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np)
{
return USB_DR_MODE_UNKNOWN;
}
static inline bool of_usb_host_tpl_support(struct device_node *np) static inline bool of_usb_host_tpl_support(struct device_node *np)
{ {
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment