On 11/20/2015 1:19 PM, John Youn wrote: > On 11/3/2015 9:49 AM, Bin Liu wrote: >> 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 <b-liu@xxxxxx> >> --- >> v5: - to simplify the code, add usb_get_dr_mode_from_string() to query >> dr_mode from string >> >> v4: - iterating all phy nodes in the associated controller >> - add of_node_put() to decrement refcount >> >> v3: search controller node from dt root, as the phy and controller nodes >> might not have the same parent. >> >> v2: move drivers/usb/phy/phy-am335x.c changes into patch 3/3. >> >> drivers/usb/common/common.c | 60 ++++++++++++++++++++++++++++++++++++++++----- >> include/linux/usb/of.h | 5 ++++ >> 2 files changed, 59 insertions(+), 6 deletions(-) >> >> diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c >> index 673d530..a11bb15 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,23 +107,70 @@ 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); >> >> +/** >> + * 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); >> + >> #ifdef CONFIG_OF >> /** >> * of_usb_host_tpl_support - to get if Targeted Peripheral List is supported >> diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h >> index c3fe9e4..3805757 100644 >> --- a/include/linux/usb/of.h >> +++ b/include/linux/usb/of.h >> @@ -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; >> > > > Hi Felipe, > > This commit in your testing/next causes compilation error: > > /home/johnyoun/linux/linux-usb/drivers/usb/common/common.c:143:18: error: redefinition of ‘of_usb_get_dr_mode_by_phy’ > enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np) > ^ > In file included from /home/johnyoun/linux/linux-usb/drivers/usb/common/common.c:18:0: > /home/johnyoun/linux/linux-usb/include/linux/usb/of.h:20:18: note: previous definition of ‘of_usb_get_dr_mode_by_phy’ was here > enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np) > ^ > make[4]: *** [drivers/usb/common/common.o] Error 1 > > I'm on non-OF config. Looks like the #ifdef CONFIG_OF should encompass the new function in the .c file. Regards, John -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html