Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: ehci-exynos: Change to use phy provided by the generic phy framework

Add the phy provider, supplied by new Exynos-usb2phy using
Generic phy framework.
Keeping the support for older USB phy intact right now, in order
to prevent any functionality break in absence of relevant
device tree side change for ehci-exynos.
Once we move to new phy in the device nodes for ehci, we can
remove the support for older phys.

Signed-off-by: Kamil Debski <k.debski@samsung.com>
[gautam.vivek@samsung.com: Addressed review comments from mailing list]
[gautam.vivek@samsung.com: Kept the code for old usb-phy, and just
added support for new exynos5-usb2phy in generic phy framework]
[gautam.vivek@samsung.com: Edited the commit message]
Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
Cc: Jingoo Han <jg1.han@samsung.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Kamil Debski and committed by
Greg Kroah-Hartman
1c17675d 7d28e54b

+124 -20
+15
Documentation/devicetree/bindings/usb/exynos-usb.txt
··· 12 12 - interrupts: interrupt number to the cpu. 13 13 - clocks: from common clock binding: handle to usb clock. 14 14 - clock-names: from common clock binding: Shall be "usbhost". 15 + - port: if in the SoC there are EHCI phys, they should be listed here. 16 + One phy per port. Each port should have following entries: 17 + - reg: port number on EHCI controller, e.g 18 + On Exynos5250, port 0 is USB2.0 otg phy 19 + port 1 is HSIC phy0 20 + port 2 is HSIC phy1 21 + - phys: from the *Generic PHY* bindings; specifying phy used by port. 15 22 16 23 Optional properties: 17 24 - samsung,vbus-gpio: if present, specifies the GPIO that ··· 34 27 35 28 clocks = <&clock 285>; 36 29 clock-names = "usbhost"; 30 + 31 + #address-cells = <1>; 32 + #size-cells = <0>; 33 + port@0 { 34 + reg = <0>; 35 + phys = <&usb2phy 1>; 36 + status = "disabled"; 37 + }; 37 38 }; 38 39 39 40 OHCI
+109 -20
drivers/usb/host/ehci-exynos.c
··· 19 19 #include <linux/module.h> 20 20 #include <linux/of.h> 21 21 #include <linux/of_gpio.h> 22 + #include <linux/phy/phy.h> 22 23 #include <linux/platform_device.h> 23 24 #include <linux/usb/phy.h> 24 25 #include <linux/usb/samsung_usb_phy.h> ··· 43 42 static const char hcd_name[] = "ehci-exynos"; 44 43 static struct hc_driver __read_mostly exynos_ehci_hc_driver; 45 44 45 + #define PHY_NUMBER 3 46 + 46 47 struct exynos_ehci_hcd { 47 48 struct clk *clk; 48 49 struct usb_phy *phy; 49 50 struct usb_otg *otg; 51 + struct phy *phy_g[PHY_NUMBER]; 50 52 }; 51 53 52 54 #define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv) 55 + 56 + static int exynos_ehci_get_phy(struct device *dev, 57 + struct exynos_ehci_hcd *exynos_ehci) 58 + { 59 + struct device_node *child; 60 + struct phy *phy; 61 + int phy_number; 62 + int ret = 0; 63 + 64 + exynos_ehci->phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 65 + if (IS_ERR(exynos_ehci->phy)) { 66 + ret = PTR_ERR(exynos_ehci->phy); 67 + if (ret != -ENXIO && ret != -ENODEV) { 68 + dev_err(dev, "no usb2 phy configured\n"); 69 + return ret; 70 + } 71 + dev_dbg(dev, "Failed to get usb2 phy\n"); 72 + } else { 73 + exynos_ehci->otg = exynos_ehci->phy->otg; 74 + } 75 + 76 + for_each_available_child_of_node(dev->of_node, child) { 77 + ret = of_property_read_u32(child, "reg", &phy_number); 78 + if (ret) { 79 + dev_err(dev, "Failed to parse device tree\n"); 80 + of_node_put(child); 81 + return ret; 82 + } 83 + 84 + if (phy_number >= PHY_NUMBER) { 85 + dev_err(dev, "Invalid number of PHYs\n"); 86 + of_node_put(child); 87 + return -EINVAL; 88 + } 89 + 90 + phy = devm_of_phy_get(dev, child, 0); 91 + of_node_put(child); 92 + if (IS_ERR(phy)) { 93 + ret = PTR_ERR(phy); 94 + if (ret != -ENOSYS && ret != -ENODEV) { 95 + dev_err(dev, "no usb2 phy configured\n"); 96 + return ret; 97 + } 98 + dev_dbg(dev, "Failed to get usb2 phy\n"); 99 + } 100 + exynos_ehci->phy_g[phy_number] = phy; 101 + } 102 + 103 + return ret; 104 + } 105 + 106 + static int exynos_ehci_phy_enable(struct device *dev) 107 + { 108 + struct usb_hcd *hcd = dev_get_drvdata(dev); 109 + struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); 110 + int i; 111 + int ret = 0; 112 + 113 + if (!IS_ERR(exynos_ehci->phy)) 114 + return usb_phy_init(exynos_ehci->phy); 115 + 116 + for (i = 0; ret == 0 && i < PHY_NUMBER; i++) 117 + if (!IS_ERR(exynos_ehci->phy_g[i])) 118 + ret = phy_power_on(exynos_ehci->phy_g[i]); 119 + if (ret) 120 + for (i--; i >= 0; i--) 121 + if (!IS_ERR(exynos_ehci->phy_g[i])) 122 + phy_power_off(exynos_ehci->phy_g[i]); 123 + 124 + return ret; 125 + } 126 + 127 + static void exynos_ehci_phy_disable(struct device *dev) 128 + { 129 + struct usb_hcd *hcd = dev_get_drvdata(dev); 130 + struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); 131 + int i; 132 + 133 + if (!IS_ERR(exynos_ehci->phy)) { 134 + usb_phy_shutdown(exynos_ehci->phy); 135 + return; 136 + } 137 + 138 + for (i = 0; i < PHY_NUMBER; i++) 139 + if (!IS_ERR(exynos_ehci->phy_g[i])) 140 + phy_power_off(exynos_ehci->phy_g[i]); 141 + } 53 142 54 143 static void exynos_setup_vbus_gpio(struct device *dev) 55 144 { ··· 165 74 struct usb_hcd *hcd; 166 75 struct ehci_hcd *ehci; 167 76 struct resource *res; 168 - struct usb_phy *phy; 169 77 int irq; 170 78 int err; 171 79 ··· 191 101 "samsung,exynos5440-ehci")) 192 102 goto skip_phy; 193 103 194 - phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); 195 - if (IS_ERR(phy)) { 196 - usb_put_hcd(hcd); 197 - dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); 198 - return -EPROBE_DEFER; 199 - } else { 200 - exynos_ehci->phy = phy; 201 - exynos_ehci->otg = phy->otg; 202 - } 104 + err = exynos_ehci_get_phy(&pdev->dev, exynos_ehci); 105 + if (err) 106 + goto fail_clk; 203 107 204 108 skip_phy: 205 109 ··· 235 151 if (exynos_ehci->otg) 236 152 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 237 153 238 - if (exynos_ehci->phy) 239 - usb_phy_init(exynos_ehci->phy); 154 + err = exynos_ehci_phy_enable(&pdev->dev); 155 + if (err) { 156 + dev_err(&pdev->dev, "Failed to enable USB phy\n"); 157 + goto fail_io; 158 + } 240 159 241 160 ehci = hcd_to_ehci(hcd); 242 161 ehci->caps = hcd->regs; ··· 259 172 return 0; 260 173 261 174 fail_add_hcd: 262 - if (exynos_ehci->phy) 263 - usb_phy_shutdown(exynos_ehci->phy); 175 + exynos_ehci_phy_disable(&pdev->dev); 264 176 fail_io: 265 177 clk_disable_unprepare(exynos_ehci->clk); 266 178 fail_clk: ··· 277 191 if (exynos_ehci->otg) 278 192 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 279 193 280 - if (exynos_ehci->phy) 281 - usb_phy_shutdown(exynos_ehci->phy); 194 + exynos_ehci_phy_disable(&pdev->dev); 282 195 283 196 clk_disable_unprepare(exynos_ehci->clk); 284 197 ··· 302 217 if (exynos_ehci->otg) 303 218 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 304 219 305 - if (exynos_ehci->phy) 306 - usb_phy_shutdown(exynos_ehci->phy); 220 + exynos_ehci_phy_disable(dev); 307 221 308 222 clk_disable_unprepare(exynos_ehci->clk); 309 223 ··· 313 229 { 314 230 struct usb_hcd *hcd = dev_get_drvdata(dev); 315 231 struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); 232 + int ret; 316 233 317 234 clk_prepare_enable(exynos_ehci->clk); 318 235 319 236 if (exynos_ehci->otg) 320 237 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 321 238 322 - if (exynos_ehci->phy) 323 - usb_phy_init(exynos_ehci->phy); 239 + ret = exynos_ehci_phy_enable(dev); 240 + if (ret) { 241 + dev_err(dev, "Failed to enable USB phy\n"); 242 + clk_disable_unprepare(exynos_ehci->clk); 243 + return ret; 244 + } 324 245 325 246 /* DMA burst Enable */ 326 247 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));