Skip to content

Commit

Permalink
usb: of: add an api to get dr_mode by the phy node
Browse files Browse the repository at this point in the history
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: Bin Liu <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
  • Loading branch information
liubiin authored and Felipe Balbi committed Dec 15, 2015
1 parent fa4dce2 commit 98bfb39
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 6 deletions.
60 changes: 54 additions & 6 deletions drivers/usb/common/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -106,24 +107,71 @@ 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)
Expand Down
5 changes: 5 additions & 0 deletions include/linux/usb/of.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@
#include <linux/usb/phy.h>

#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);
int of_usb_update_otg_caps(struct device_node *np,
struct usb_otg_caps *otg_caps);
#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)
{
return false;
Expand Down

0 comments on commit 98bfb39

Please sign in to comment.