aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-tegra.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-05-01 11:28:49 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-01 14:06:36 -0400
commitebf20de453042c066a289b90dd14d59de03dba2f (patch)
treea705f2a68b1f51f5eecef1336e7523f6bb26e591 /drivers/usb/host/ehci-tegra.c
parent69964ea4c7b68c9399f7977aa5b9aa6539a6a98a (diff)
EHCI: update PM methods in ehci-tegra.c
This patch (as1547) rearranges the Power Management parts of the ehci-tegra driver to match the conventions used in other EHCI platform drivers. In particular, the controller should not be powered down by the root hub's suspend routine; the controller's power level should be managed by the controller's own PM methods. The end result of the patch is that the standard ehci_bus_suspend() and ehci_bus_resume() methods can be used instead of special-purpose routines. The driver now uses the standard dev_pm_ops methods instead of legacy power management. Since there is no supported wakeup mechanism for the controller, runtime suspend is forbidden by default (this can be overridden via sysfs, if desired). These adjustments are needed in order to make ehci-tegra compatible with recent changes to the USB core. The core now checks the root hub's status following bus suspend; if the controller is automatically powered down during bus suspend then the check will fail and the root hub will be resumed immediately. Doing the controller power-down in a separate method avoids this problem. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Stephen Warren <swarren@wwwdotorg.org> Tested-by: Stephen Warren <swarren@wwwdotorg.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ehci-tegra.c')
-rw-r--r--drivers/usb/host/ehci-tegra.c375
1 files changed, 195 insertions, 180 deletions
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 86183366647f..73f3525e6921 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -24,6 +24,7 @@
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <linux/of.h> 25#include <linux/of.h>
26#include <linux/of_gpio.h> 26#include <linux/of_gpio.h>
27#include <linux/pm_runtime.h>
27 28
28#include <mach/usb_phy.h> 29#include <mach/usb_phy.h>
29#include <mach/iomap.h> 30#include <mach/iomap.h>
@@ -37,9 +38,7 @@ struct tegra_ehci_hcd {
37 struct clk *emc_clk; 38 struct clk *emc_clk;
38 struct usb_phy *transceiver; 39 struct usb_phy *transceiver;
39 int host_resumed; 40 int host_resumed;
40 int bus_suspended;
41 int port_resuming; 41 int port_resuming;
42 int power_down_on_bus_suspend;
43 enum tegra_usb_phy_port_speed port_speed; 42 enum tegra_usb_phy_port_speed port_speed;
44}; 43};
45 44
@@ -273,120 +272,6 @@ static void tegra_ehci_restart(struct usb_hcd *hcd)
273 up_write(&ehci_cf_port_reset_rwsem); 272 up_write(&ehci_cf_port_reset_rwsem);
274} 273}
275 274
276static int tegra_usb_suspend(struct usb_hcd *hcd)
277{
278 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
279 struct ehci_regs __iomem *hw = tegra->ehci->regs;
280 unsigned long flags;
281
282 spin_lock_irqsave(&tegra->ehci->lock, flags);
283
284 tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
285 ehci_halt(tegra->ehci);
286 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
287
288 spin_unlock_irqrestore(&tegra->ehci->lock, flags);
289
290 tegra_ehci_power_down(hcd);
291 return 0;
292}
293
294static int tegra_usb_resume(struct usb_hcd *hcd)
295{
296 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
297 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
298 struct ehci_regs __iomem *hw = ehci->regs;
299 unsigned long val;
300
301 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
302 tegra_ehci_power_up(hcd);
303
304 if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
305 /* Wait for the phy to detect new devices
306 * before we restart the controller */
307 msleep(10);
308 goto restart;
309 }
310
311 /* Force the phy to keep data lines in suspend state */
312 tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
313
314 /* Enable host mode */
315 tdi_reset(ehci);
316
317 /* Enable Port Power */
318 val = readl(&hw->port_status[0]);
319 val |= PORT_POWER;
320 writel(val, &hw->port_status[0]);
321 udelay(10);
322
323 /* Check if the phy resume from LP0. When the phy resume from LP0
324 * USB register will be reset. */
325 if (!readl(&hw->async_next)) {
326 /* Program the field PTC based on the saved speed mode */
327 val = readl(&hw->port_status[0]);
328 val &= ~PORT_TEST(~0);
329 if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
330 val |= PORT_TEST_FORCE;
331 else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
332 val |= PORT_TEST(6);
333 else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
334 val |= PORT_TEST(7);
335 writel(val, &hw->port_status[0]);
336 udelay(10);
337
338 /* Disable test mode by setting PTC field to NORMAL_OP */
339 val = readl(&hw->port_status[0]);
340 val &= ~PORT_TEST(~0);
341 writel(val, &hw->port_status[0]);
342 udelay(10);
343 }
344
345 /* Poll until CCS is enabled */
346 if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
347 PORT_CONNECT, 2000)) {
348 pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
349 goto restart;
350 }
351
352 /* Poll until PE is enabled */
353 if (handshake(ehci, &hw->port_status[0], PORT_PE,
354 PORT_PE, 2000)) {
355 pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
356 goto restart;
357 }
358
359 /* Clear the PCI status, to avoid an interrupt taken upon resume */
360 val = readl(&hw->status);
361 val |= STS_PCD;
362 writel(val, &hw->status);
363
364 /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
365 val = readl(&hw->port_status[0]);
366 if ((val & PORT_POWER) && (val & PORT_PE)) {
367 val |= PORT_SUSPEND;
368 writel(val, &hw->port_status[0]);
369
370 /* Wait until port suspend completes */
371 if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
372 PORT_SUSPEND, 1000)) {
373 pr_err("%s: timeout waiting for PORT_SUSPEND\n",
374 __func__);
375 goto restart;
376 }
377 }
378
379 tegra_ehci_phy_restore_end(tegra->phy);
380 return 0;
381
382restart:
383 if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
384 tegra_ehci_phy_restore_end(tegra->phy);
385
386 tegra_ehci_restart(hcd);
387 return 0;
388}
389
390static void tegra_ehci_shutdown(struct usb_hcd *hcd) 275static void tegra_ehci_shutdown(struct usb_hcd *hcd)
391{ 276{
392 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 277 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
@@ -434,36 +319,6 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
434 return retval; 319 return retval;
435} 320}
436 321
437#ifdef CONFIG_PM
438static int tegra_ehci_bus_suspend(struct usb_hcd *hcd)
439{
440 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
441 int error_status = 0;
442
443 error_status = ehci_bus_suspend(hcd);
444 if (!error_status && tegra->power_down_on_bus_suspend) {
445 tegra_usb_suspend(hcd);
446 tegra->bus_suspended = 1;
447 }
448
449 return error_status;
450}
451
452static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
453{
454 struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
455
456 if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) {
457 tegra_usb_resume(hcd);
458 tegra->bus_suspended = 0;
459 }
460
461 tegra_usb_phy_preresume(tegra->phy);
462 tegra->port_resuming = 1;
463 return ehci_bus_resume(hcd);
464}
465#endif
466
467struct temp_buffer { 322struct temp_buffer {
468 void *kmalloc_ptr; 323 void *kmalloc_ptr;
469 void *old_xfer_buffer; 324 void *old_xfer_buffer;
@@ -574,8 +429,8 @@ static const struct hc_driver tegra_ehci_hc_driver = {
574 .hub_control = tegra_ehci_hub_control, 429 .hub_control = tegra_ehci_hub_control,
575 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 430 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
576#ifdef CONFIG_PM 431#ifdef CONFIG_PM
577 .bus_suspend = tegra_ehci_bus_suspend, 432 .bus_suspend = ehci_bus_suspend,
578 .bus_resume = tegra_ehci_bus_resume, 433 .bus_resume = ehci_bus_resume,
579#endif 434#endif
580 .relinquish_port = ehci_relinquish_port, 435 .relinquish_port = ehci_relinquish_port,
581 .port_handed_over = ehci_port_handed_over, 436 .port_handed_over = ehci_port_handed_over,
@@ -608,6 +463,183 @@ static int setup_vbus_gpio(struct platform_device *pdev)
608 return err; 463 return err;
609} 464}
610 465
466#ifdef CONFIG_PM
467
468static int controller_suspend(struct device *dev)
469{
470 struct tegra_ehci_hcd *tegra =
471 platform_get_drvdata(to_platform_device(dev));
472 struct ehci_hcd *ehci = tegra->ehci;
473 struct usb_hcd *hcd = ehci_to_hcd(ehci);
474 struct ehci_regs __iomem *hw = ehci->regs;
475 unsigned long flags;
476
477 if (time_before(jiffies, ehci->next_statechange))
478 msleep(10);
479
480 spin_lock_irqsave(&ehci->lock, flags);
481
482 tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
483 ehci_halt(ehci);
484 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
485
486 spin_unlock_irqrestore(&ehci->lock, flags);
487
488 tegra_ehci_power_down(hcd);
489 return 0;
490}
491
492static int controller_resume(struct device *dev)
493{
494 struct tegra_ehci_hcd *tegra =
495 platform_get_drvdata(to_platform_device(dev));
496 struct ehci_hcd *ehci = tegra->ehci;
497 struct usb_hcd *hcd = ehci_to_hcd(ehci);
498 struct ehci_regs __iomem *hw = ehci->regs;
499 unsigned long val;
500
501 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
502 tegra_ehci_power_up(hcd);
503
504 if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
505 /* Wait for the phy to detect new devices
506 * before we restart the controller */
507 msleep(10);
508 goto restart;
509 }
510
511 /* Force the phy to keep data lines in suspend state */
512 tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
513
514 /* Enable host mode */
515 tdi_reset(ehci);
516
517 /* Enable Port Power */
518 val = readl(&hw->port_status[0]);
519 val |= PORT_POWER;
520 writel(val, &hw->port_status[0]);
521 udelay(10);
522
523 /* Check if the phy resume from LP0. When the phy resume from LP0
524 * USB register will be reset. */
525 if (!readl(&hw->async_next)) {
526 /* Program the field PTC based on the saved speed mode */
527 val = readl(&hw->port_status[0]);
528 val &= ~PORT_TEST(~0);
529 if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
530 val |= PORT_TEST_FORCE;
531 else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
532 val |= PORT_TEST(6);
533 else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
534 val |= PORT_TEST(7);
535 writel(val, &hw->port_status[0]);
536 udelay(10);
537
538 /* Disable test mode by setting PTC field to NORMAL_OP */
539 val = readl(&hw->port_status[0]);
540 val &= ~PORT_TEST(~0);
541 writel(val, &hw->port_status[0]);
542 udelay(10);
543 }
544
545 /* Poll until CCS is enabled */
546 if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
547 PORT_CONNECT, 2000)) {
548 pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
549 goto restart;
550 }
551
552 /* Poll until PE is enabled */
553 if (handshake(ehci, &hw->port_status[0], PORT_PE,
554 PORT_PE, 2000)) {
555 pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
556 goto restart;
557 }
558
559 /* Clear the PCI status, to avoid an interrupt taken upon resume */
560 val = readl(&hw->status);
561 val |= STS_PCD;
562 writel(val, &hw->status);
563
564 /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
565 val = readl(&hw->port_status[0]);
566 if ((val & PORT_POWER) && (val & PORT_PE)) {
567 val |= PORT_SUSPEND;
568 writel(val, &hw->port_status[0]);
569
570 /* Wait until port suspend completes */
571 if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
572 PORT_SUSPEND, 1000)) {
573 pr_err("%s: timeout waiting for PORT_SUSPEND\n",
574 __func__);
575 goto restart;
576 }
577 }
578
579 tegra_ehci_phy_restore_end(tegra->phy);
580 goto done;
581
582 restart:
583 if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
584 tegra_ehci_phy_restore_end(tegra->phy);
585
586 tegra_ehci_restart(hcd);
587
588 done:
589 tegra_usb_phy_preresume(tegra->phy);
590 tegra->port_resuming = 1;
591 return 0;
592}
593
594static int tegra_ehci_suspend(struct device *dev)
595{
596 struct tegra_ehci_hcd *tegra =
597 platform_get_drvdata(to_platform_device(dev));
598 struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
599 int rc = 0;
600
601 /*
602 * When system sleep is supported and USB controller wakeup is
603 * implemented: If the controller is runtime-suspended and the
604 * wakeup setting needs to be changed, call pm_runtime_resume().
605 */
606 if (HCD_HW_ACCESSIBLE(hcd))
607 rc = controller_suspend(dev);
608 return rc;
609}
610
611static int tegra_ehci_resume(struct device *dev)
612{
613 int rc;
614
615 rc = controller_resume(dev);
616 if (rc == 0) {
617 pm_runtime_disable(dev);
618 pm_runtime_set_active(dev);
619 pm_runtime_enable(dev);
620 }
621 return rc;
622}
623
624static int tegra_ehci_runtime_suspend(struct device *dev)
625{
626 return controller_suspend(dev);
627}
628
629static int tegra_ehci_runtime_resume(struct device *dev)
630{
631 return controller_resume(dev);
632}
633
634static const struct dev_pm_ops tegra_ehci_pm_ops = {
635 .suspend = tegra_ehci_suspend,
636 .resume = tegra_ehci_resume,
637 .runtime_suspend = tegra_ehci_runtime_suspend,
638 .runtime_resume = tegra_ehci_runtime_resume,
639};
640
641#endif
642
611static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); 643static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
612 644
613static int tegra_ehci_probe(struct platform_device *pdev) 645static int tegra_ehci_probe(struct platform_device *pdev)
@@ -722,7 +754,6 @@ static int tegra_ehci_probe(struct platform_device *pdev)
722 } 754 }
723 755
724 tegra->host_resumed = 1; 756 tegra->host_resumed = 1;
725 tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend;
726 tegra->ehci = hcd_to_ehci(hcd); 757 tegra->ehci = hcd_to_ehci(hcd);
727 758
728 irq = platform_get_irq(pdev, 0); 759 irq = platform_get_irq(pdev, 0);
@@ -746,6 +777,14 @@ static int tegra_ehci_probe(struct platform_device *pdev)
746 goto fail; 777 goto fail;
747 } 778 }
748 779
780 pm_runtime_set_active(&pdev->dev);
781 pm_runtime_get_noresume(&pdev->dev);
782
783 /* Don't skip the pm_runtime_forbid call if wakeup isn't working */
784 /* if (!pdata->power_down_on_bus_suspend) */
785 pm_runtime_forbid(&pdev->dev);
786 pm_runtime_enable(&pdev->dev);
787 pm_runtime_put_sync(&pdev->dev);
749 return err; 788 return err;
750 789
751fail: 790fail:
@@ -772,33 +811,6 @@ fail_hcd:
772 return err; 811 return err;
773} 812}
774 813
775#ifdef CONFIG_PM
776static int tegra_ehci_resume(struct platform_device *pdev)
777{
778 struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
779 struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
780
781 if (tegra->bus_suspended)
782 return 0;
783
784 return tegra_usb_resume(hcd);
785}
786
787static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state)
788{
789 struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
790 struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
791
792 if (tegra->bus_suspended)
793 return 0;
794
795 if (time_before(jiffies, tegra->ehci->next_statechange))
796 msleep(10);
797
798 return tegra_usb_suspend(hcd);
799}
800#endif
801
802static int tegra_ehci_remove(struct platform_device *pdev) 814static int tegra_ehci_remove(struct platform_device *pdev)
803{ 815{
804 struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); 816 struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
@@ -807,6 +819,10 @@ static int tegra_ehci_remove(struct platform_device *pdev)
807 if (tegra == NULL || hcd == NULL) 819 if (tegra == NULL || hcd == NULL)
808 return -EINVAL; 820 return -EINVAL;
809 821
822 pm_runtime_get_sync(&pdev->dev);
823 pm_runtime_disable(&pdev->dev);
824 pm_runtime_put_noidle(&pdev->dev);
825
810#ifdef CONFIG_USB_OTG_UTILS 826#ifdef CONFIG_USB_OTG_UTILS
811 if (tegra->transceiver) { 827 if (tegra->transceiver) {
812 otg_set_host(tegra->transceiver->otg, NULL); 828 otg_set_host(tegra->transceiver->otg, NULL);
@@ -847,13 +863,12 @@ static struct of_device_id tegra_ehci_of_match[] __devinitdata = {
847static struct platform_driver tegra_ehci_driver = { 863static struct platform_driver tegra_ehci_driver = {
848 .probe = tegra_ehci_probe, 864 .probe = tegra_ehci_probe,
849 .remove = tegra_ehci_remove, 865 .remove = tegra_ehci_remove,
850#ifdef CONFIG_PM
851 .suspend = tegra_ehci_suspend,
852 .resume = tegra_ehci_resume,
853#endif
854 .shutdown = tegra_ehci_hcd_shutdown, 866 .shutdown = tegra_ehci_hcd_shutdown,
855 .driver = { 867 .driver = {
856 .name = "tegra-ehci", 868 .name = "tegra-ehci",
857 .of_match_table = tegra_ehci_of_match, 869 .of_match_table = tegra_ehci_of_match,
870#ifdef CONFIG_PM
871 .pm = &tegra_ehci_pm_ops,
872#endif
858 } 873 }
859}; 874};