diff options
Diffstat (limited to 'drivers/usb/host/ehci-omap.c')
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 76 |
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 | ||
74 | struct omap_hcd { | ||
75 | struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */ | ||
76 | int nports; | ||
77 | }; | ||
73 | 78 | ||
74 | static inline void ehci_write(void __iomem *base, u32 reg, u32 val) | 79 | static inline void ehci_write(void __iomem *base, u32 reg, u32 val) |
75 | { | 80 | { |
@@ -178,7 +183,8 @@ static void disable_put_regulator( | |||
178 | static struct hc_driver __read_mostly ehci_omap_hc_driver; | 183 | static struct hc_driver __read_mostly ehci_omap_hc_driver; |
179 | 184 | ||
180 | static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { | 185 | static 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 | */ |
191 | static int ehci_hcd_omap_probe(struct platform_device *pdev) | 197 | static 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) | |||
275 | err_pm_runtime: | 309 | err_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 | |||
313 | err_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 | */ |
292 | static int ehci_hcd_omap_remove(struct platform_device *pdev) | 333 | static 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 | ||