.. | .. |
---|
19 | 19 | |
---|
20 | 20 | #include "ohci.h" |
---|
21 | 21 | |
---|
22 | | -#define DRIVER_DESC "OHCI EXYNOS driver" |
---|
| 22 | +#define DRIVER_DESC "OHCI Exynos driver" |
---|
23 | 23 | |
---|
24 | 24 | static const char hcd_name[] = "ohci-exynos"; |
---|
25 | 25 | static struct hc_driver __read_mostly exynos_ohci_hc_driver; |
---|
.. | .. |
---|
30 | 30 | |
---|
31 | 31 | struct exynos_ohci_hcd { |
---|
32 | 32 | struct clk *clk; |
---|
| 33 | + struct device_node *of_node; |
---|
33 | 34 | struct phy *phy[PHY_NUMBER]; |
---|
| 35 | + bool legacy_phy; |
---|
34 | 36 | }; |
---|
35 | 37 | |
---|
36 | 38 | static int exynos_ohci_get_phy(struct device *dev, |
---|
.. | .. |
---|
38 | 40 | { |
---|
39 | 41 | struct device_node *child; |
---|
40 | 42 | struct phy *phy; |
---|
41 | | - int phy_number; |
---|
| 43 | + int phy_number, num_phys; |
---|
42 | 44 | int ret; |
---|
43 | 45 | |
---|
44 | 46 | /* Get PHYs for the controller */ |
---|
| 47 | + num_phys = of_count_phandle_with_args(dev->of_node, "phys", |
---|
| 48 | + "#phy-cells"); |
---|
| 49 | + for (phy_number = 0; phy_number < num_phys; phy_number++) { |
---|
| 50 | + phy = devm_of_phy_get_by_index(dev, dev->of_node, phy_number); |
---|
| 51 | + if (IS_ERR(phy)) |
---|
| 52 | + return PTR_ERR(phy); |
---|
| 53 | + exynos_ohci->phy[phy_number] = phy; |
---|
| 54 | + } |
---|
| 55 | + if (num_phys > 0) |
---|
| 56 | + return 0; |
---|
| 57 | + |
---|
| 58 | + /* Get PHYs using legacy bindings */ |
---|
45 | 59 | for_each_available_child_of_node(dev->of_node, child) { |
---|
46 | 60 | ret = of_property_read_u32(child, "reg", &phy_number); |
---|
47 | 61 | if (ret) { |
---|
.. | .. |
---|
72 | 86 | } |
---|
73 | 87 | } |
---|
74 | 88 | |
---|
| 89 | + exynos_ohci->legacy_phy = true; |
---|
75 | 90 | return 0; |
---|
76 | 91 | } |
---|
77 | 92 | |
---|
.. | .. |
---|
169 | 184 | goto fail_io; |
---|
170 | 185 | } |
---|
171 | 186 | |
---|
| 187 | + /* |
---|
| 188 | + * Workaround: reset of_node pointer to avoid conflict between legacy |
---|
| 189 | + * Exynos OHCI port subnodes and generic USB device bindings |
---|
| 190 | + */ |
---|
| 191 | + exynos_ohci->of_node = pdev->dev.of_node; |
---|
| 192 | + if (exynos_ohci->legacy_phy) |
---|
| 193 | + pdev->dev.of_node = NULL; |
---|
| 194 | + |
---|
172 | 195 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); |
---|
173 | 196 | if (err) { |
---|
174 | 197 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); |
---|
.. | .. |
---|
179 | 202 | |
---|
180 | 203 | fail_add_hcd: |
---|
181 | 204 | exynos_ohci_phy_disable(&pdev->dev); |
---|
| 205 | + pdev->dev.of_node = exynos_ohci->of_node; |
---|
182 | 206 | fail_io: |
---|
183 | 207 | clk_disable_unprepare(exynos_ohci->clk); |
---|
184 | 208 | fail_clk: |
---|
.. | .. |
---|
191 | 215 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
---|
192 | 216 | struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); |
---|
193 | 217 | |
---|
| 218 | + pdev->dev.of_node = exynos_ohci->of_node; |
---|
| 219 | + |
---|
194 | 220 | usb_remove_hcd(hcd); |
---|
195 | 221 | |
---|
196 | 222 | exynos_ohci_phy_disable(&pdev->dev); |
---|