aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorPavankumar Kondeti <pkondeti@codeaurora.org>2010-12-07 07:23:57 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-12-10 17:23:32 -0500
commit8bb6a164b906bb7ca319202f85b30e3ef096cd65 (patch)
tree25405ae8262dde87ea8ccf19277067c10095999f /drivers/usb
parentb0848aea10da186372582f33152efdda43944f26 (diff)
USB: EHCI: msm: Add support for power management
Enable runtime PM and mark no_callbacks flag. OTG device, parent of HCD takes care of putting hardware into low power mode. Adjust port power wakeup flags during system suspend and resume. Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/ehci-msm.c57
2 files changed, 57 insertions, 2 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index d8665ec0565b..b9cc31172fbd 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -150,7 +150,7 @@ config USB_EHCI_MSM
150 Enables support for the USB Host controller present on the 150 Enables support for the USB Host controller present on the
151 Qualcomm chipsets. Root Hub has inbuilt TT. 151 Qualcomm chipsets. Root Hub has inbuilt TT.
152 This driver depends on OTG driver for PHY initialization, 152 This driver depends on OTG driver for PHY initialization,
153 clock management, powering up VBUS. 153 clock management, powering up VBUS, and power management.
154 154
155config USB_EHCI_HCD_PPC_OF 155config USB_EHCI_HCD_PPC_OF
156 bool "EHCI support for PPC USB controller on OF platform bus" 156 bool "EHCI support for PPC USB controller on OF platform bus"
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 9ed855986599..413f4deca532 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -25,6 +25,7 @@
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/clk.h> 26#include <linux/clk.h>
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/pm_runtime.h>
28 29
29#include <linux/usb/otg.h> 30#include <linux/usb/otg.h>
30#include <linux/usb/msm_hsusb_hw.h> 31#include <linux/usb/msm_hsusb_hw.h>
@@ -239,7 +240,8 @@ static int ehci_msm_probe(struct platform_device *pdev)
239 240
240 /* 241 /*
241 * OTG driver takes care of PHY initialization, clock management, 242 * OTG driver takes care of PHY initialization, clock management,
242 * powering up VBUS and mapping of registers address space. 243 * powering up VBUS, mapping of registers address space and power
244 * management.
243 */ 245 */
244 otg = otg_get_transceiver(); 246 otg = otg_get_transceiver();
245 if (!otg) { 247 if (!otg) {
@@ -255,6 +257,13 @@ static int ehci_msm_probe(struct platform_device *pdev)
255 } 257 }
256 258
257 device_init_wakeup(&pdev->dev, 1); 259 device_init_wakeup(&pdev->dev, 1);
260 /*
261 * OTG device parent of HCD takes care of putting
262 * hardware into low power mode.
263 */
264 pm_runtime_no_callbacks(&pdev->dev);
265 pm_runtime_enable(&pdev->dev);
266
258 return 0; 267 return 0;
259 268
260put_transceiver: 269put_transceiver:
@@ -272,6 +281,8 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev)
272 struct usb_hcd *hcd = platform_get_drvdata(pdev); 281 struct usb_hcd *hcd = platform_get_drvdata(pdev);
273 282
274 device_init_wakeup(&pdev->dev, 0); 283 device_init_wakeup(&pdev->dev, 0);
284 pm_runtime_disable(&pdev->dev);
285 pm_runtime_set_suspended(&pdev->dev);
275 286
276 otg_set_host(otg, NULL); 287 otg_set_host(otg, NULL);
277 otg_put_transceiver(otg); 288 otg_put_transceiver(otg);
@@ -281,10 +292,54 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev)
281 return 0; 292 return 0;
282} 293}
283 294
295#ifdef CONFIG_PM
296static int ehci_msm_pm_suspend(struct device *dev)
297{
298 struct usb_hcd *hcd = dev_get_drvdata(dev);
299 bool wakeup = device_may_wakeup(dev);
300
301 dev_dbg(dev, "ehci-msm PM suspend\n");
302
303 /*
304 * EHCI helper function has also the same check before manipulating
305 * port wakeup flags. We do check here the same condition before
306 * calling the same helper function to avoid bringing hardware
307 * from Low power mode when there is no need for adjusting port
308 * wakeup flags.
309 */
310 if (hcd->self.root_hub->do_remote_wakeup && !wakeup) {
311 pm_runtime_resume(dev);
312 ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
313 wakeup);
314 }
315
316 return 0;
317}
318
319static int ehci_msm_pm_resume(struct device *dev)
320{
321 struct usb_hcd *hcd = dev_get_drvdata(dev);
322
323 dev_dbg(dev, "ehci-msm PM resume\n");
324 ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd));
325
326 return 0;
327}
328#else
329#define ehci_msm_pm_suspend NULL
330#define ehci_msm_pm_resume NULL
331#endif
332
333static const struct dev_pm_ops ehci_msm_dev_pm_ops = {
334 .suspend = ehci_msm_pm_suspend,
335 .resume = ehci_msm_pm_resume,
336};
337
284static struct platform_driver ehci_msm_driver = { 338static struct platform_driver ehci_msm_driver = {
285 .probe = ehci_msm_probe, 339 .probe = ehci_msm_probe,
286 .remove = __devexit_p(ehci_msm_remove), 340 .remove = __devexit_p(ehci_msm_remove),
287 .driver = { 341 .driver = {
288 .name = "msm_hsusb_host", 342 .name = "msm_hsusb_host",
343 .pm = &ehci_msm_dev_pm_ops,
289 }, 344 },
290}; 345};