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 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