aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-omap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-omap.c')
-rw-r--r--drivers/usb/host/ehci-omap.c76
1 files changed, 62 insertions, 14 deletions
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 70e8e6f33d42..6b8b7e5358a6 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -4,10 +4,11 @@
4 * Bus Glue for the EHCI controllers in OMAP3/4 4 * Bus Glue for the EHCI controllers in OMAP3/4
5 * Tested on several OMAP3 boards, and OMAP4 Pandaboard 5 * Tested on several OMAP3 boards, and OMAP4 Pandaboard
6 * 6 *
7 * Copyright (C) 2007-2011 Texas Instruments, Inc. 7 * Copyright (C) 2007-2013 Texas Instruments, Inc.
8 * Author: Vikram Pandita <vikram.pandita@ti.com> 8 * Author: Vikram Pandita <vikram.pandita@ti.com>
9 * Author: Anand Gadiyar <gadiyar@ti.com> 9 * Author: Anand Gadiyar <gadiyar@ti.com>
10 * Author: Keshava Munegowda <keshava_mgowda@ti.com> 10 * Author: Keshava Munegowda <keshava_mgowda@ti.com>
11 * Author: Roger Quadros <rogerq@ti.com>
11 * 12 *
12 * Copyright (C) 2009 Nokia Corporation 13 * Copyright (C) 2009 Nokia Corporation
13 * Contact: Felipe Balbi <felipe.balbi@nokia.com> 14 * Contact: Felipe Balbi <felipe.balbi@nokia.com>
@@ -70,6 +71,10 @@ static const char hcd_name[] = "ehci-omap";
70 71
71/*-------------------------------------------------------------------------*/ 72/*-------------------------------------------------------------------------*/
72 73
74struct omap_hcd {
75 struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */
76 int nports;
77};
73 78
74static inline void ehci_write(void __iomem *base, u32 reg, u32 val) 79static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
75{ 80{
@@ -178,7 +183,8 @@ static void disable_put_regulator(
178static struct hc_driver __read_mostly ehci_omap_hc_driver; 183static struct hc_driver __read_mostly ehci_omap_hc_driver;
179 184
180static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { 185static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
181 .reset = omap_ehci_init, 186 .reset = omap_ehci_init,
187 .extra_priv_size = sizeof(struct omap_hcd),
182}; 188};
183 189
184/** 190/**
@@ -190,15 +196,16 @@ static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
190 */ 196 */
191static int ehci_hcd_omap_probe(struct platform_device *pdev) 197static int ehci_hcd_omap_probe(struct platform_device *pdev)
192{ 198{
193 struct device *dev = &pdev->dev; 199 struct device *dev = &pdev->dev;
194 struct usbhs_omap_platform_data *pdata = dev->platform_data; 200 struct usbhs_omap_platform_data *pdata = dev->platform_data;
195 struct resource *res; 201 struct resource *res;
196 struct usb_hcd *hcd; 202 struct usb_hcd *hcd;
197 void __iomem *regs; 203 void __iomem *regs;
198 int ret = -ENODEV; 204 int ret = -ENODEV;
199 int irq; 205 int irq;
200 int i; 206 int i;
201 char supply[7]; 207 char supply[7];
208 struct omap_hcd *omap;
202 209
203 if (usb_disabled()) 210 if (usb_disabled())
204 return -ENODEV; 211 return -ENODEV;
@@ -231,6 +238,33 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
231 hcd->rsrc_len = resource_size(res); 238 hcd->rsrc_len = resource_size(res);
232 hcd->regs = regs; 239 hcd->regs = regs;
233 240
241 omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
242 omap->nports = pdata->nports;
243
244 platform_set_drvdata(pdev, hcd);
245
246 /* get the PHY devices if needed */
247 for (i = 0 ; i < omap->nports ; i++) {
248 struct usb_phy *phy;
249
250 if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
251 continue;
252
253 /* get the PHY device */
254 phy = devm_usb_get_phy_dev(dev, i);
255 if (IS_ERR(phy) || !phy) {
256 ret = IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV;
257 dev_err(dev, "Can't get PHY device for port %d: %d\n",
258 i, ret);
259 goto err_phy;
260 }
261
262 omap->phy[i] = phy;
263 usb_phy_init(omap->phy[i]);
264 /* bring PHY out of suspend */
265 usb_phy_set_suspend(omap->phy[i], 0);
266 }
267
234 /* get ehci regulator and enable */ 268 /* get ehci regulator and enable */
235 for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { 269 for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
236 if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) { 270 if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
@@ -275,6 +309,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
275err_pm_runtime: 309err_pm_runtime:
276 disable_put_regulator(pdata); 310 disable_put_regulator(pdata);
277 pm_runtime_put_sync(dev); 311 pm_runtime_put_sync(dev);
312
313err_phy:
314 for (i = 0; i < omap->nports; i++) {
315 if (omap->phy[i])
316 usb_phy_shutdown(omap->phy[i]);
317 }
318
278 usb_put_hcd(hcd); 319 usb_put_hcd(hcd);
279 320
280 return ret; 321 return ret;
@@ -291,13 +332,20 @@ err_pm_runtime:
291 */ 332 */
292static int ehci_hcd_omap_remove(struct platform_device *pdev) 333static int ehci_hcd_omap_remove(struct platform_device *pdev)
293{ 334{
294 struct device *dev = &pdev->dev; 335 struct device *dev = &pdev->dev;
295 struct usb_hcd *hcd = dev_get_drvdata(dev); 336 struct usb_hcd *hcd = dev_get_drvdata(dev);
337 struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
338 int i;
296 339
297 usb_remove_hcd(hcd); 340 usb_remove_hcd(hcd);
298 disable_put_regulator(dev->platform_data); 341 disable_put_regulator(dev->platform_data);
299 usb_put_hcd(hcd);
300 342
343 for (i = 0; i < omap->nports; i++) {
344 if (omap->phy[i])
345 usb_phy_shutdown(omap->phy[i]);
346 }
347
348 usb_put_hcd(hcd);
301 pm_runtime_put_sync(dev); 349 pm_runtime_put_sync(dev);
302 pm_runtime_disable(dev); 350 pm_runtime_disable(dev);
303 351