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> --- drivers/usb/common/common.c | 27 +++++++++++++++++++++++++++ drivers/usb/phy/phy-am335x.c | 5 +++++ include/linux/usb/of.h | 6 ++++++ 3 files changed, 38 insertions(+) diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index b530fd4..3c7dee8 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -114,6 +114,33 @@ 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 a phy device. 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; + struct device_node *phy; + + controller = of_get_parent(phy_np); + do { + controller = of_find_node_with_property(controller, "phys"); + if (!controller) + return USB_DR_MODE_UNKNOWN; + + phy = of_parse_phandle(controller, "phys", 0); + } while (phy != phy_np); + + return of_usb_get_dr_mode(controller); +} +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/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index 90b67a4..d65add6 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -8,6 +8,7 @@ #include <linux/regulator/consumer.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/usb/of.h> #include "am35x-phy-control.h" #include "phy-generic.h" @@ -16,6 +17,7 @@ struct am335x_phy { struct usb_phy_generic usb_phy_gen; struct phy_control *phy_ctrl; int id; + enum usb_dr_mode dr_mode; }; static int am335x_init(struct usb_phy *phy) @@ -46,12 +48,15 @@ static int am335x_phy_probe(struct platform_device *pdev) am_phy->phy_ctrl = am335x_get_phy_control(dev); if (!am_phy->phy_ctrl) return -EPROBE_DEFER; + am_phy->id = of_alias_get_id(pdev->dev.of_node, "phy"); if (am_phy->id < 0) { dev_err(&pdev->dev, "Missing PHY id: %d\n", am_phy->id); return am_phy->id; } + am_phy->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node); + ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL); if (ret) return ret; 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