diff options
author | Hans de Goede <hdegoede@redhat.com> | 2016-06-10 05:46:25 -0400 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2016-06-21 03:52:39 -0400 |
commit | ce15ed4c5dfb3f7757e6611902aed5db253af977 (patch) | |
tree | 1aca75d0045e608b29c3451acc09a67d64198c27 | |
parent | 882bd9fc46321c9d4721b376039a142cbfe8a17a (diff) |
USB: Fix of_usb_get_dr_mode_by_phy with a shared phy block
Some SoCs have a single phy-hw-block with multiple phys, this is
modelled by a single phy dts node, so we end up with multiple
controller nodes with a phys property pointing to the phy-node
of the otg-phy.
Only one of these controllers typically is an otg controller, yet we
were checking the first controller who uses a phy from the block and
then end up looking for a dr_mode property in e.g. the ehci controller.
This commit fixes this by adding an arg0 parameter to
of_usb_get_dr_mode_by_phy and make of_usb_get_dr_mode_by_phy
check that this matches the phandle args[0] value when looking for
the otg controller.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
-rw-r--r-- | drivers/usb/common/common.c | 26 | ||||
-rw-r--r-- | drivers/usb/phy/phy-am335x.c | 2 | ||||
-rw-r--r-- | include/linux/usb/of.h | 4 |
3 files changed, 23 insertions, 9 deletions
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index e3d01619d6b3..5ef8da6e67c3 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c | |||
@@ -131,15 +131,17 @@ EXPORT_SYMBOL_GPL(usb_get_dr_mode); | |||
131 | * of_usb_get_dr_mode_by_phy - Get dual role mode for the controller device | 131 | * of_usb_get_dr_mode_by_phy - Get dual role mode for the controller device |
132 | * which is associated with the given phy device_node | 132 | * which is associated with the given phy device_node |
133 | * @np: Pointer to the given phy device_node | 133 | * @np: Pointer to the given phy device_node |
134 | * @arg0: phandle args[0] for phy's with #phy-cells >= 1, or -1 for | ||
135 | * phys which do not have phy-cells | ||
134 | * | 136 | * |
135 | * In dts a usb controller associates with phy devices. The function gets | 137 | * In dts a usb controller associates with phy devices. The function gets |
136 | * the string from property 'dr_mode' of the controller associated with the | 138 | * the string from property 'dr_mode' of the controller associated with the |
137 | * given phy device node, and returns the correspondig enum usb_dr_mode. | 139 | * given phy device node, and returns the correspondig enum usb_dr_mode. |
138 | */ | 140 | */ |
139 | enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np) | 141 | enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0) |
140 | { | 142 | { |
141 | struct device_node *controller = NULL; | 143 | struct device_node *controller = NULL; |
142 | struct device_node *phy; | 144 | struct of_phandle_args args; |
143 | const char *dr_mode; | 145 | const char *dr_mode; |
144 | int index; | 146 | int index; |
145 | int err; | 147 | int err; |
@@ -148,12 +150,24 @@ enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np) | |||
148 | controller = of_find_node_with_property(controller, "phys"); | 150 | controller = of_find_node_with_property(controller, "phys"); |
149 | index = 0; | 151 | index = 0; |
150 | do { | 152 | do { |
151 | phy = of_parse_phandle(controller, "phys", index); | 153 | if (arg0 == -1) { |
152 | of_node_put(phy); | 154 | args.np = of_parse_phandle(controller, "phys", |
153 | if (phy == phy_np) | 155 | index); |
156 | args.args_count = 0; | ||
157 | } else { | ||
158 | err = of_parse_phandle_with_args(controller, | ||
159 | "phys", "#phy-cells", | ||
160 | index, &args); | ||
161 | if (err) | ||
162 | break; | ||
163 | } | ||
164 | |||
165 | of_node_put(args.np); | ||
166 | if (args.np == np && (args.args_count == 0 || | ||
167 | args.args[0] == arg0)) | ||
154 | goto finish; | 168 | goto finish; |
155 | index++; | 169 | index++; |
156 | } while (phy); | 170 | } while (args.np); |
157 | } while (controller); | 171 | } while (controller); |
158 | 172 | ||
159 | finish: | 173 | finish: |
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index a262a4343f29..7e5aece769da 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c | |||
@@ -54,7 +54,7 @@ static int am335x_phy_probe(struct platform_device *pdev) | |||
54 | return am_phy->id; | 54 | return am_phy->id; |
55 | } | 55 | } |
56 | 56 | ||
57 | am_phy->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node); | 57 | am_phy->dr_mode = of_usb_get_dr_mode_by_phy(pdev->dev.of_node, -1); |
58 | 58 | ||
59 | ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL); | 59 | ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL); |
60 | if (ret) | 60 | if (ret) |
diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index de3237fce6b2..5ff9032ee1b4 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/usb/phy.h> | 12 | #include <linux/usb/phy.h> |
13 | 13 | ||
14 | #if IS_ENABLED(CONFIG_OF) | 14 | #if IS_ENABLED(CONFIG_OF) |
15 | enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *phy_np); | 15 | enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0); |
16 | bool of_usb_host_tpl_support(struct device_node *np); | 16 | bool of_usb_host_tpl_support(struct device_node *np); |
17 | int of_usb_update_otg_caps(struct device_node *np, | 17 | int of_usb_update_otg_caps(struct device_node *np, |
18 | struct usb_otg_caps *otg_caps); | 18 | struct usb_otg_caps *otg_caps); |
@@ -20,7 +20,7 @@ struct device_node *usb_of_get_child_node(struct device_node *parent, | |||
20 | int portnum); | 20 | int portnum); |
21 | #else | 21 | #else |
22 | static inline enum usb_dr_mode | 22 | static inline enum usb_dr_mode |
23 | of_usb_get_dr_mode_by_phy(struct device_node *phy_np) | 23 | of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0) |
24 | { | 24 | { |
25 | return USB_DR_MODE_UNKNOWN; | 25 | return USB_DR_MODE_UNKNOWN; |
26 | } | 26 | } |