aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorKamil Debski <k.debski@samsung.com>2014-05-05 01:02:28 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-27 17:50:20 -0400
commit1c17675d6c733232f10afceec0bcd016ad3849f0 (patch)
treecf222f131fbca4ca0128aea1ab65294acd5b781e /drivers/usb/host
parent7d28e54b8d8dee31323433f5563534fc273bcda8 (diff)
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>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-exynos.c129
1 files changed, 109 insertions, 20 deletions
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index 4d763dc91f70..c7081c75de8a 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -19,6 +19,7 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/of.h> 20#include <linux/of.h>
21#include <linux/of_gpio.h> 21#include <linux/of_gpio.h>
22#include <linux/phy/phy.h>
22#include <linux/platform_device.h> 23#include <linux/platform_device.h>
23#include <linux/usb/phy.h> 24#include <linux/usb/phy.h>
24#include <linux/usb/samsung_usb_phy.h> 25#include <linux/usb/samsung_usb_phy.h>
@@ -42,14 +43,104 @@
42static const char hcd_name[] = "ehci-exynos"; 43static const char hcd_name[] = "ehci-exynos";
43static struct hc_driver __read_mostly exynos_ehci_hc_driver; 44static struct hc_driver __read_mostly exynos_ehci_hc_driver;
44 45
46#define PHY_NUMBER 3
47
45struct exynos_ehci_hcd { 48struct exynos_ehci_hcd {
46 struct clk *clk; 49 struct clk *clk;
47 struct usb_phy *phy; 50 struct usb_phy *phy;
48 struct usb_otg *otg; 51 struct usb_otg *otg;
52 struct phy *phy_g[PHY_NUMBER];
49}; 53};
50 54
51#define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv) 55#define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv)
52 56
57static int exynos_ehci_get_phy(struct device *dev,
58 struct exynos_ehci_hcd *exynos_ehci)
59{
60 struct device_node *child;
61 struct phy *phy;
62 int phy_number;
63 int ret = 0;
64
65 exynos_ehci->phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
66 if (IS_ERR(exynos_ehci->phy)) {
67 ret = PTR_ERR(exynos_ehci->phy);
68 if (ret != -ENXIO && ret != -ENODEV) {
69 dev_err(dev, "no usb2 phy configured\n");
70 return ret;
71 }
72 dev_dbg(dev, "Failed to get usb2 phy\n");
73 } else {
74 exynos_ehci->otg = exynos_ehci->phy->otg;
75 }
76
77 for_each_available_child_of_node(dev->of_node, child) {
78 ret = of_property_read_u32(child, "reg", &phy_number);
79 if (ret) {
80 dev_err(dev, "Failed to parse device tree\n");
81 of_node_put(child);
82 return ret;
83 }
84
85 if (phy_number >= PHY_NUMBER) {
86 dev_err(dev, "Invalid number of PHYs\n");
87 of_node_put(child);
88 return -EINVAL;
89 }
90
91 phy = devm_of_phy_get(dev, child, 0);
92 of_node_put(child);
93 if (IS_ERR(phy)) {
94 ret = PTR_ERR(phy);
95 if (ret != -ENOSYS && ret != -ENODEV) {
96 dev_err(dev, "no usb2 phy configured\n");
97 return ret;
98 }
99 dev_dbg(dev, "Failed to get usb2 phy\n");
100 }
101 exynos_ehci->phy_g[phy_number] = phy;
102 }
103
104 return ret;
105}
106
107static int exynos_ehci_phy_enable(struct device *dev)
108{
109 struct usb_hcd *hcd = dev_get_drvdata(dev);
110 struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
111 int i;
112 int ret = 0;
113
114 if (!IS_ERR(exynos_ehci->phy))
115 return usb_phy_init(exynos_ehci->phy);
116
117 for (i = 0; ret == 0 && i < PHY_NUMBER; i++)
118 if (!IS_ERR(exynos_ehci->phy_g[i]))
119 ret = phy_power_on(exynos_ehci->phy_g[i]);
120 if (ret)
121 for (i--; i >= 0; i--)
122 if (!IS_ERR(exynos_ehci->phy_g[i]))
123 phy_power_off(exynos_ehci->phy_g[i]);
124
125 return ret;
126}
127
128static void exynos_ehci_phy_disable(struct device *dev)
129{
130 struct usb_hcd *hcd = dev_get_drvdata(dev);
131 struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
132 int i;
133
134 if (!IS_ERR(exynos_ehci->phy)) {
135 usb_phy_shutdown(exynos_ehci->phy);
136 return;
137 }
138
139 for (i = 0; i < PHY_NUMBER; i++)
140 if (!IS_ERR(exynos_ehci->phy_g[i]))
141 phy_power_off(exynos_ehci->phy_g[i]);
142}
143
53static void exynos_setup_vbus_gpio(struct device *dev) 144static void exynos_setup_vbus_gpio(struct device *dev)
54{ 145{
55 int err; 146 int err;
@@ -74,7 +165,6 @@ static int exynos_ehci_probe(struct platform_device *pdev)
74 struct usb_hcd *hcd; 165 struct usb_hcd *hcd;
75 struct ehci_hcd *ehci; 166 struct ehci_hcd *ehci;
76 struct resource *res; 167 struct resource *res;
77 struct usb_phy *phy;
78 int irq; 168 int irq;
79 int err; 169 int err;
80 170
@@ -101,15 +191,9 @@ static int exynos_ehci_probe(struct platform_device *pdev)
101 "samsung,exynos5440-ehci")) 191 "samsung,exynos5440-ehci"))
102 goto skip_phy; 192 goto skip_phy;
103 193
104 phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); 194 err = exynos_ehci_get_phy(&pdev->dev, exynos_ehci);
105 if (IS_ERR(phy)) { 195 if (err)
106 usb_put_hcd(hcd); 196 goto fail_clk;
107 dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
108 return -EPROBE_DEFER;
109 } else {
110 exynos_ehci->phy = phy;
111 exynos_ehci->otg = phy->otg;
112 }
113 197
114skip_phy: 198skip_phy:
115 199
@@ -151,8 +235,11 @@ skip_phy:
151 if (exynos_ehci->otg) 235 if (exynos_ehci->otg)
152 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 236 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
153 237
154 if (exynos_ehci->phy) 238 err = exynos_ehci_phy_enable(&pdev->dev);
155 usb_phy_init(exynos_ehci->phy); 239 if (err) {
240 dev_err(&pdev->dev, "Failed to enable USB phy\n");
241 goto fail_io;
242 }
156 243
157 ehci = hcd_to_ehci(hcd); 244 ehci = hcd_to_ehci(hcd);
158 ehci->caps = hcd->regs; 245 ehci->caps = hcd->regs;
@@ -172,8 +259,7 @@ skip_phy:
172 return 0; 259 return 0;
173 260
174fail_add_hcd: 261fail_add_hcd:
175 if (exynos_ehci->phy) 262 exynos_ehci_phy_disable(&pdev->dev);
176 usb_phy_shutdown(exynos_ehci->phy);
177fail_io: 263fail_io:
178 clk_disable_unprepare(exynos_ehci->clk); 264 clk_disable_unprepare(exynos_ehci->clk);
179fail_clk: 265fail_clk:
@@ -191,8 +277,7 @@ static int exynos_ehci_remove(struct platform_device *pdev)
191 if (exynos_ehci->otg) 277 if (exynos_ehci->otg)
192 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 278 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
193 279
194 if (exynos_ehci->phy) 280 exynos_ehci_phy_disable(&pdev->dev);
195 usb_phy_shutdown(exynos_ehci->phy);
196 281
197 clk_disable_unprepare(exynos_ehci->clk); 282 clk_disable_unprepare(exynos_ehci->clk);
198 283
@@ -217,8 +302,7 @@ static int exynos_ehci_suspend(struct device *dev)
217 if (exynos_ehci->otg) 302 if (exynos_ehci->otg)
218 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 303 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
219 304
220 if (exynos_ehci->phy) 305 exynos_ehci_phy_disable(dev);
221 usb_phy_shutdown(exynos_ehci->phy);
222 306
223 clk_disable_unprepare(exynos_ehci->clk); 307 clk_disable_unprepare(exynos_ehci->clk);
224 308
@@ -229,14 +313,19 @@ static int exynos_ehci_resume(struct device *dev)
229{ 313{
230 struct usb_hcd *hcd = dev_get_drvdata(dev); 314 struct usb_hcd *hcd = dev_get_drvdata(dev);
231 struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd); 315 struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
316 int ret;
232 317
233 clk_prepare_enable(exynos_ehci->clk); 318 clk_prepare_enable(exynos_ehci->clk);
234 319
235 if (exynos_ehci->otg) 320 if (exynos_ehci->otg)
236 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); 321 exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
237 322
238 if (exynos_ehci->phy) 323 ret = exynos_ehci_phy_enable(dev);
239 usb_phy_init(exynos_ehci->phy); 324 if (ret) {
325 dev_err(dev, "Failed to enable USB phy\n");
326 clk_disable_unprepare(exynos_ehci->clk);
327 return ret;
328 }
240 329
241 /* DMA burst Enable */ 330 /* DMA burst Enable */
242 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); 331 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));