summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/ehci-platform.c40
-rw-r--r--include/linux/usb/ehci_pdriver.h8
2 files changed, 45 insertions, 3 deletions
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index a2aaef618aea..91acdde8d21f 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -105,10 +105,18 @@ static int __devinit ehci_platform_probe(struct platform_device *dev)
return -ENXIO;
}
+ if (pdata->power_on) {
+ err = pdata->power_on(dev);
+ if (err < 0)
+ return err;
+ }
+
hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
dev_name(&dev->dev));
- if (!hcd)
- return -ENOMEM;
+ if (!hcd) {
+ err = -ENOMEM;
+ goto err_power;
+ }
hcd->rsrc_start = res_mem->start;
hcd->rsrc_len = resource_size(res_mem);
@@ -136,12 +144,17 @@ err_release_region:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_put_hcd:
usb_put_hcd(hcd);
+err_power:
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
return err;
}
static int __devexit ehci_platform_remove(struct platform_device *dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
+ struct usb_ehci_pdata *pdata = dev->dev.platform_data;
usb_remove_hcd(hcd);
iounmap(hcd->regs);
@@ -149,6 +162,9 @@ static int __devexit ehci_platform_remove(struct platform_device *dev)
usb_put_hcd(hcd);
platform_set_drvdata(dev, NULL);
+ if (pdata->power_off)
+ pdata->power_off(dev);
+
return 0;
}
@@ -157,14 +173,32 @@ static int __devexit ehci_platform_remove(struct platform_device *dev)
static int ehci_platform_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct usb_ehci_pdata *pdata = dev->platform_data;
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
bool do_wakeup = device_may_wakeup(dev);
+ int ret;
+
+ ret = ehci_suspend(hcd, do_wakeup);
- return ehci_suspend(hcd, do_wakeup);
+ if (pdata->power_suspend)
+ pdata->power_suspend(pdev);
+
+ return ret;
}
static int ehci_platform_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct usb_ehci_pdata *pdata = dev->platform_data;
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+
+ if (pdata->power_on) {
+ int err = pdata->power_on(pdev);
+ if (err < 0)
+ return err;
+ }
ehci_resume(hcd, false);
return 0;
diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h
index 1894f42fe3f7..c9d09f8b7ff2 100644
--- a/include/linux/usb/ehci_pdriver.h
+++ b/include/linux/usb/ehci_pdriver.h
@@ -41,6 +41,14 @@ struct usb_ehci_pdata {
unsigned big_endian_mmio:1;
unsigned port_power_on:1;
unsigned port_power_off:1;
+
+ /* Turn on all power and clocks */
+ int (*power_on)(struct platform_device *pdev);
+ /* Turn off all power and clocks */
+ void (*power_off)(struct platform_device *pdev);
+ /* Turn on only VBUS suspend power and hotplug detection,
+ * turn off everything else */
+ void (*power_suspend)(struct platform_device *pdev);
};
#endif /* __USB_CORE_EHCI_PDRIVER_H */