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> --- 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 | 36 ++++++++++++++++++++++++++++++++++++ include/linux/usb/of.h | 6 ++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index b530fd4..e3da800 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -114,6 +114,42 @@ enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) EXPORT_SYMBOL_GPL(of_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; + enum usb_dr_mode dr_mode; + int index; + + 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: + dr_mode = of_usb_get_dr_mode(controller); + of_node_put(controller); + + return dr_mode; +} +EXPORT_SYMBOL_GPL(of_usb_get_dr_mode_by_phy); + +/** * of_usb_get_maximum_speed - Get maximum requested speed for a given USB * controller. * @np: Pointer to the given device_node diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index cfe0528..14ebd5a 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h @@ -13,6 +13,7 @@ #if IS_ENABLED(CONFIG_OF) enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np); +enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np); enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np); bool of_usb_host_tpl_support(struct device_node *np); #else @@ -21,6 +22,11 @@ static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) return USB_DR_MODE_UNKNOWN; } +enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np) +{ + return USB_DR_MODE_UNKNOWN; +} + static inline enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np) { -- 1.8.4 -- 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