aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorVivek Gautam <gautam.vivek@samsung.com>2013-01-22 08:00:42 -0500
committerFelipe Balbi <balbi@ti.com>2013-01-23 06:39:18 -0500
commitd233c196ce1a3a33901b75ca818c85825683afba (patch)
tree691c2f8e1edf28a9bcd8e25c37a573da1e139f35 /drivers/usb/host
parent8c1b3e16e902b010f79e2d299927ec43b495f1c7 (diff)
USB: ehci-s5p: Add phy driver support
Adding the phy driver to ehci-s5p. Keeping the platform data for continuing the smooth operation for boards which still uses it Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com> Acked-by: Jingoo Han <jg1.han@samsung.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-s5p.c80
1 files changed, 59 insertions, 21 deletions
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 46ca5efac82b..d603e6ec19a5 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -17,6 +17,7 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/of_gpio.h> 18#include <linux/of_gpio.h>
19#include <linux/platform_data/usb-ehci-s5p.h> 19#include <linux/platform_data/usb-ehci-s5p.h>
20#include <linux/usb/phy.h>
20#include <linux/usb/samsung_usb_phy.h> 21#include <linux/usb/samsung_usb_phy.h>
21#include <plat/usb-phy.h> 22#include <plat/usb-phy.h>
22 23
@@ -33,6 +34,9 @@ struct s5p_ehci_hcd {
33 struct device *dev; 34 struct device *dev;
34 struct usb_hcd *hcd; 35 struct usb_hcd *hcd;
35 struct clk *clk; 36 struct clk *clk;
37 struct usb_phy *phy;
38 struct usb_otg *otg;
39 struct s5p_ehci_platdata *pdata;
36}; 40};
37 41
38static const struct hc_driver s5p_ehci_hc_driver = { 42static const struct hc_driver s5p_ehci_hc_driver = {
@@ -66,6 +70,26 @@ static const struct hc_driver s5p_ehci_hc_driver = {
66 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 70 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
67}; 71};
68 72
73static void s5p_ehci_phy_enable(struct s5p_ehci_hcd *s5p_ehci)
74{
75 struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
76
77 if (s5p_ehci->phy)
78 usb_phy_init(s5p_ehci->phy);
79 else if (s5p_ehci->pdata->phy_init)
80 s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
81}
82
83static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci)
84{
85 struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
86
87 if (s5p_ehci->phy)
88 usb_phy_shutdown(s5p_ehci->phy);
89 else if (s5p_ehci->pdata->phy_exit)
90 s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
91}
92
69static void s5p_setup_vbus_gpio(struct platform_device *pdev) 93static void s5p_setup_vbus_gpio(struct platform_device *pdev)
70{ 94{
71 int err; 95 int err;
@@ -88,20 +112,15 @@ static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32);
88 112
89static int s5p_ehci_probe(struct platform_device *pdev) 113static int s5p_ehci_probe(struct platform_device *pdev)
90{ 114{
91 struct s5p_ehci_platdata *pdata; 115 struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
92 struct s5p_ehci_hcd *s5p_ehci; 116 struct s5p_ehci_hcd *s5p_ehci;
93 struct usb_hcd *hcd; 117 struct usb_hcd *hcd;
94 struct ehci_hcd *ehci; 118 struct ehci_hcd *ehci;
95 struct resource *res; 119 struct resource *res;
120 struct usb_phy *phy;
96 int irq; 121 int irq;
97 int err; 122 int err;
98 123
99 pdata = pdev->dev.platform_data;
100 if (!pdata) {
101 dev_err(&pdev->dev, "No platform data defined\n");
102 return -EINVAL;
103 }
104
105 /* 124 /*
106 * Right now device-tree probed devices don't get dma_mask set. 125 * Right now device-tree probed devices don't get dma_mask set.
107 * Since shared usb code relies on it, set it here for now. 126 * Since shared usb code relies on it, set it here for now.
@@ -119,6 +138,20 @@ static int s5p_ehci_probe(struct platform_device *pdev)
119 if (!s5p_ehci) 138 if (!s5p_ehci)
120 return -ENOMEM; 139 return -ENOMEM;
121 140
141 phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
142 if (IS_ERR_OR_NULL(phy)) {
143 /* Fallback to pdata */
144 if (!pdata) {
145 dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
146 return -EPROBE_DEFER;
147 } else {
148 s5p_ehci->pdata = pdata;
149 }
150 } else {
151 s5p_ehci->phy = phy;
152 s5p_ehci->otg = phy->otg;
153 }
154
122 s5p_ehci->dev = &pdev->dev; 155 s5p_ehci->dev = &pdev->dev;
123 156
124 hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev, 157 hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev,
@@ -164,8 +197,10 @@ static int s5p_ehci_probe(struct platform_device *pdev)
164 goto fail_io; 197 goto fail_io;
165 } 198 }
166 199
167 if (pdata->phy_init) 200 if (s5p_ehci->otg)
168 pdata->phy_init(pdev, USB_PHY_TYPE_HOST); 201 s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
202
203 s5p_ehci_phy_enable(s5p_ehci);
169 204
170 ehci = hcd_to_ehci(hcd); 205 ehci = hcd_to_ehci(hcd);
171 ehci->caps = hcd->regs; 206 ehci->caps = hcd->regs;
@@ -176,13 +211,15 @@ static int s5p_ehci_probe(struct platform_device *pdev)
176 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 211 err = usb_add_hcd(hcd, irq, IRQF_SHARED);
177 if (err) { 212 if (err) {
178 dev_err(&pdev->dev, "Failed to add USB HCD\n"); 213 dev_err(&pdev->dev, "Failed to add USB HCD\n");
179 goto fail_io; 214 goto fail_add_hcd;
180 } 215 }
181 216
182 platform_set_drvdata(pdev, s5p_ehci); 217 platform_set_drvdata(pdev, s5p_ehci);
183 218
184 return 0; 219 return 0;
185 220
221fail_add_hcd:
222 s5p_ehci_phy_disable(s5p_ehci);
186fail_io: 223fail_io:
187 clk_disable_unprepare(s5p_ehci->clk); 224 clk_disable_unprepare(s5p_ehci->clk);
188fail_clk: 225fail_clk:
@@ -192,14 +229,15 @@ fail_clk:
192 229
193static int s5p_ehci_remove(struct platform_device *pdev) 230static int s5p_ehci_remove(struct platform_device *pdev)
194{ 231{
195 struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
196 struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); 232 struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
197 struct usb_hcd *hcd = s5p_ehci->hcd; 233 struct usb_hcd *hcd = s5p_ehci->hcd;
198 234
199 usb_remove_hcd(hcd); 235 usb_remove_hcd(hcd);
200 236
201 if (pdata && pdata->phy_exit) 237 if (s5p_ehci->otg)
202 pdata->phy_exit(pdev, USB_PHY_TYPE_HOST); 238 s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
239
240 s5p_ehci_phy_disable(s5p_ehci);
203 241
204 clk_disable_unprepare(s5p_ehci->clk); 242 clk_disable_unprepare(s5p_ehci->clk);
205 243
@@ -223,14 +261,14 @@ static int s5p_ehci_suspend(struct device *dev)
223 struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); 261 struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
224 struct usb_hcd *hcd = s5p_ehci->hcd; 262 struct usb_hcd *hcd = s5p_ehci->hcd;
225 bool do_wakeup = device_may_wakeup(dev); 263 bool do_wakeup = device_may_wakeup(dev);
226 struct platform_device *pdev = to_platform_device(dev);
227 struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
228 int rc; 264 int rc;
229 265
230 rc = ehci_suspend(hcd, do_wakeup); 266 rc = ehci_suspend(hcd, do_wakeup);
231 267
232 if (pdata && pdata->phy_exit) 268 if (s5p_ehci->otg)
233 pdata->phy_exit(pdev, USB_PHY_TYPE_HOST); 269 s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
270
271 s5p_ehci_phy_disable(s5p_ehci);
234 272
235 clk_disable_unprepare(s5p_ehci->clk); 273 clk_disable_unprepare(s5p_ehci->clk);
236 274
@@ -241,13 +279,13 @@ static int s5p_ehci_resume(struct device *dev)
241{ 279{
242 struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); 280 struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
243 struct usb_hcd *hcd = s5p_ehci->hcd; 281 struct usb_hcd *hcd = s5p_ehci->hcd;
244 struct platform_device *pdev = to_platform_device(dev);
245 struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
246 282
247 clk_prepare_enable(s5p_ehci->clk); 283 clk_prepare_enable(s5p_ehci->clk);
248 284
249 if (pdata && pdata->phy_init) 285 if (s5p_ehci->otg)
250 pdata->phy_init(pdev, USB_PHY_TYPE_HOST); 286 s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
287
288 s5p_ehci_phy_enable(s5p_ehci);
251 289
252 /* DMA burst Enable */ 290 /* DMA burst Enable */
253 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); 291 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));