aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/platform.c296
-rw-r--r--include/linux/platform_device.h1
2 files changed, 289 insertions, 8 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 911ec600fe71..3f940393d6c7 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -453,6 +453,8 @@ int platform_driver_register(struct platform_driver *drv)
453 drv->driver.suspend = platform_drv_suspend; 453 drv->driver.suspend = platform_drv_suspend;
454 if (drv->resume) 454 if (drv->resume)
455 drv->driver.resume = platform_drv_resume; 455 drv->driver.resume = platform_drv_resume;
456 if (drv->pm)
457 drv->driver.pm = &drv->pm->base;
456 return driver_register(&drv->driver); 458 return driver_register(&drv->driver);
457} 459}
458EXPORT_SYMBOL_GPL(platform_driver_register); 460EXPORT_SYMBOL_GPL(platform_driver_register);
@@ -560,7 +562,9 @@ static int platform_match(struct device *dev, struct device_driver *drv)
560 return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); 562 return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
561} 563}
562 564
563static int platform_suspend(struct device *dev, pm_message_t mesg) 565#ifdef CONFIG_PM_SLEEP
566
567static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
564{ 568{
565 int ret = 0; 569 int ret = 0;
566 570
@@ -570,7 +574,7 @@ static int platform_suspend(struct device *dev, pm_message_t mesg)
570 return ret; 574 return ret;
571} 575}
572 576
573static int platform_suspend_late(struct device *dev, pm_message_t mesg) 577static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg)
574{ 578{
575 struct platform_driver *drv = to_platform_driver(dev->driver); 579 struct platform_driver *drv = to_platform_driver(dev->driver);
576 struct platform_device *pdev; 580 struct platform_device *pdev;
@@ -583,7 +587,7 @@ static int platform_suspend_late(struct device *dev, pm_message_t mesg)
583 return ret; 587 return ret;
584} 588}
585 589
586static int platform_resume_early(struct device *dev) 590static int platform_legacy_resume_early(struct device *dev)
587{ 591{
588 struct platform_driver *drv = to_platform_driver(dev->driver); 592 struct platform_driver *drv = to_platform_driver(dev->driver);
589 struct platform_device *pdev; 593 struct platform_device *pdev;
@@ -596,7 +600,7 @@ static int platform_resume_early(struct device *dev)
596 return ret; 600 return ret;
597} 601}
598 602
599static int platform_resume(struct device *dev) 603static int platform_legacy_resume(struct device *dev)
600{ 604{
601 int ret = 0; 605 int ret = 0;
602 606
@@ -606,15 +610,291 @@ static int platform_resume(struct device *dev)
606 return ret; 610 return ret;
607} 611}
608 612
613static int platform_pm_prepare(struct device *dev)
614{
615 struct device_driver *drv = dev->driver;
616 int ret = 0;
617
618 if (drv && drv->pm && drv->pm->prepare)
619 ret = drv->pm->prepare(dev);
620
621 return ret;
622}
623
624static void platform_pm_complete(struct device *dev)
625{
626 struct device_driver *drv = dev->driver;
627
628 if (drv && drv->pm && drv->pm->complete)
629 drv->pm->complete(dev);
630}
631
632#ifdef CONFIG_SUSPEND
633
634static int platform_pm_suspend(struct device *dev)
635{
636 struct device_driver *drv = dev->driver;
637 int ret = 0;
638
639 if (drv && drv->pm) {
640 if (drv->pm->suspend)
641 ret = drv->pm->suspend(dev);
642 } else {
643 ret = platform_legacy_suspend(dev, PMSG_SUSPEND);
644 }
645
646 return ret;
647}
648
649static int platform_pm_suspend_noirq(struct device *dev)
650{
651 struct platform_driver *pdrv;
652 int ret = 0;
653
654 if (!dev->driver)
655 return 0;
656
657 pdrv = to_platform_driver(dev->driver);
658 if (pdrv->pm) {
659 if (pdrv->pm->suspend_noirq)
660 ret = pdrv->pm->suspend_noirq(dev);
661 } else {
662 ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND);
663 }
664
665 return ret;
666}
667
668static int platform_pm_resume(struct device *dev)
669{
670 struct device_driver *drv = dev->driver;
671 int ret = 0;
672
673 if (drv && drv->pm) {
674 if (drv->pm->resume)
675 ret = drv->pm->resume(dev);
676 } else {
677 ret = platform_legacy_resume(dev);
678 }
679
680 return ret;
681}
682
683static int platform_pm_resume_noirq(struct device *dev)
684{
685 struct platform_driver *pdrv;
686 int ret = 0;
687
688 if (!dev->driver)
689 return 0;
690
691 pdrv = to_platform_driver(dev->driver);
692 if (pdrv->pm) {
693 if (pdrv->pm->resume_noirq)
694 ret = pdrv->pm->resume_noirq(dev);
695 } else {
696 ret = platform_legacy_resume_early(dev);
697 }
698
699 return ret;
700}
701
702#else /* !CONFIG_SUSPEND */
703
704#define platform_pm_suspend NULL
705#define platform_pm_resume NULL
706#define platform_pm_suspend_noirq NULL
707#define platform_pm_resume_noirq NULL
708
709#endif /* !CONFIG_SUSPEND */
710
711#ifdef CONFIG_HIBERNATION
712
713static int platform_pm_freeze(struct device *dev)
714{
715 struct device_driver *drv = dev->driver;
716 int ret = 0;
717
718 if (!drv)
719 return 0;
720
721 if (drv->pm) {
722 if (drv->pm->freeze)
723 ret = drv->pm->freeze(dev);
724 } else {
725 ret = platform_legacy_suspend(dev, PMSG_FREEZE);
726 }
727
728 return ret;
729}
730
731static int platform_pm_freeze_noirq(struct device *dev)
732{
733 struct platform_driver *pdrv;
734 int ret = 0;
735
736 if (!dev->driver)
737 return 0;
738
739 pdrv = to_platform_driver(dev->driver);
740 if (pdrv->pm) {
741 if (pdrv->pm->freeze_noirq)
742 ret = pdrv->pm->freeze_noirq(dev);
743 } else {
744 ret = platform_legacy_suspend_late(dev, PMSG_FREEZE);
745 }
746
747 return ret;
748}
749
750static int platform_pm_thaw(struct device *dev)
751{
752 struct device_driver *drv = dev->driver;
753 int ret = 0;
754
755 if (drv && drv->pm) {
756 if (drv->pm->thaw)
757 ret = drv->pm->thaw(dev);
758 } else {
759 ret = platform_legacy_resume(dev);
760 }
761
762 return ret;
763}
764
765static int platform_pm_thaw_noirq(struct device *dev)
766{
767 struct platform_driver *pdrv;
768 int ret = 0;
769
770 if (!dev->driver)
771 return 0;
772
773 pdrv = to_platform_driver(dev->driver);
774 if (pdrv->pm) {
775 if (pdrv->pm->thaw_noirq)
776 ret = pdrv->pm->thaw_noirq(dev);
777 } else {
778 ret = platform_legacy_resume_early(dev);
779 }
780
781 return ret;
782}
783
784static int platform_pm_poweroff(struct device *dev)
785{
786 struct device_driver *drv = dev->driver;
787 int ret = 0;
788
789 if (drv && drv->pm) {
790 if (drv->pm->poweroff)
791 ret = drv->pm->poweroff(dev);
792 } else {
793 ret = platform_legacy_suspend(dev, PMSG_HIBERNATE);
794 }
795
796 return ret;
797}
798
799static int platform_pm_poweroff_noirq(struct device *dev)
800{
801 struct platform_driver *pdrv;
802 int ret = 0;
803
804 if (!dev->driver)
805 return 0;
806
807 pdrv = to_platform_driver(dev->driver);
808 if (pdrv->pm) {
809 if (pdrv->pm->poweroff_noirq)
810 ret = pdrv->pm->poweroff_noirq(dev);
811 } else {
812 ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE);
813 }
814
815 return ret;
816}
817
818static int platform_pm_restore(struct device *dev)
819{
820 struct device_driver *drv = dev->driver;
821 int ret = 0;
822
823 if (drv && drv->pm) {
824 if (drv->pm->restore)
825 ret = drv->pm->restore(dev);
826 } else {
827 ret = platform_legacy_resume(dev);
828 }
829
830 return ret;
831}
832
833static int platform_pm_restore_noirq(struct device *dev)
834{
835 struct platform_driver *pdrv;
836 int ret = 0;
837
838 if (!dev->driver)
839 return 0;
840
841 pdrv = to_platform_driver(dev->driver);
842 if (pdrv->pm) {
843 if (pdrv->pm->restore_noirq)
844 ret = pdrv->pm->restore_noirq(dev);
845 } else {
846 ret = platform_legacy_resume_early(dev);
847 }
848
849 return ret;
850}
851
852#else /* !CONFIG_HIBERNATION */
853
854#define platform_pm_freeze NULL
855#define platform_pm_thaw NULL
856#define platform_pm_poweroff NULL
857#define platform_pm_restore NULL
858#define platform_pm_freeze_noirq NULL
859#define platform_pm_thaw_noirq NULL
860#define platform_pm_poweroff_noirq NULL
861#define platform_pm_restore_noirq NULL
862
863#endif /* !CONFIG_HIBERNATION */
864
865struct pm_ext_ops platform_pm_ops = {
866 .base = {
867 .prepare = platform_pm_prepare,
868 .complete = platform_pm_complete,
869 .suspend = platform_pm_suspend,
870 .resume = platform_pm_resume,
871 .freeze = platform_pm_freeze,
872 .thaw = platform_pm_thaw,
873 .poweroff = platform_pm_poweroff,
874 .restore = platform_pm_restore,
875 },
876 .suspend_noirq = platform_pm_suspend_noirq,
877 .resume_noirq = platform_pm_resume_noirq,
878 .freeze_noirq = platform_pm_freeze_noirq,
879 .thaw_noirq = platform_pm_thaw_noirq,
880 .poweroff_noirq = platform_pm_poweroff_noirq,
881 .restore_noirq = platform_pm_restore_noirq,
882};
883
884#define PLATFORM_PM_OPS_PTR &platform_pm_ops
885
886#else /* !CONFIG_PM_SLEEP */
887
888#define PLATFORM_PM_OPS_PTR NULL
889
890#endif /* !CONFIG_PM_SLEEP */
891
609struct bus_type platform_bus_type = { 892struct bus_type platform_bus_type = {
610 .name = "platform", 893 .name = "platform",
611 .dev_attrs = platform_dev_attrs, 894 .dev_attrs = platform_dev_attrs,
612 .match = platform_match, 895 .match = platform_match,
613 .uevent = platform_uevent, 896 .uevent = platform_uevent,
614 .suspend = platform_suspend, 897 .pm = PLATFORM_PM_OPS_PTR,
615 .suspend_late = platform_suspend_late,
616 .resume_early = platform_resume_early,
617 .resume = platform_resume,
618}; 898};
619EXPORT_SYMBOL_GPL(platform_bus_type); 899EXPORT_SYMBOL_GPL(platform_bus_type);
620 900
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 3261681c82a4..95ac21ab3a09 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -53,6 +53,7 @@ struct platform_driver {
53 int (*suspend_late)(struct platform_device *, pm_message_t state); 53 int (*suspend_late)(struct platform_device *, pm_message_t state);
54 int (*resume_early)(struct platform_device *); 54 int (*resume_early)(struct platform_device *);
55 int (*resume)(struct platform_device *); 55 int (*resume)(struct platform_device *);
56 struct pm_ext_ops *pm;
56 struct device_driver driver; 57 struct device_driver driver;
57}; 58};
58 59