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 <[email protected]>
> ---
> 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html