diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-12 22:27:24 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-12 22:27:24 (GMT) |
commit | 09cea96caa59fabab3030c53bd698b9b568d959a (patch) | |
tree | a991cdc0c887fdcda37f4b751ee98d3db9559f4e /drivers/of/platform.c | |
parent | 6eb7365db6f3a4a9d8d9922bb0b800f9cbaad641 (diff) | |
parent | e090aa80321b64c3b793f3b047e31ecf1af9538d (diff) | |
download | linux-fsl-qoriq-09cea96caa59fabab3030c53bd698b9b568d959a.tar.xz |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (151 commits)
powerpc: Fix usage of 64-bit instruction in 32-bit altivec code
MAINTAINERS: Add PowerPC patterns
powerpc/pseries: Track previous CPPR values to correctly EOI interrupts
powerpc/pseries: Correct pseries/dlpar.c build break without CONFIG_SMP
powerpc: Make "intspec" pointers in irq_host->xlate() const
powerpc/8xx: DTLB Miss cleanup
powerpc/8xx: Remove DIRTY pte handling in DTLB Error.
powerpc/8xx: Start using dcbX instructions in various copy routines
powerpc/8xx: Restore _PAGE_WRITETHRU
powerpc/8xx: Add missing Guarded setting in DTLB Error.
powerpc/8xx: Fixup DAR from buggy dcbX instructions.
powerpc/8xx: Tag DAR with 0x00f0 to catch buggy instructions.
powerpc/8xx: Update TLB asm so it behaves as linux mm expects.
powerpc/8xx: Invalidate non present TLBs
powerpc/pseries: Serialize cpu hotplug operations during deactivate Vs deallocate
pseries/pseries: Add code to online/offline CPUs of a DLPAR node
powerpc: stop_this_cpu: remove the cpu from the online map.
powerpc/pseries: Add kernel based CPU DLPAR handling
sysfs/cpu: Add probe/release files
powerpc/pseries: Kernel DLPAR Infrastructure
...
Diffstat (limited to 'drivers/of/platform.c')
-rw-r--r-- | drivers/of/platform.c | 305 |
1 files changed, 290 insertions, 15 deletions
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 298de0f..d58ade1 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -65,47 +65,322 @@ static int of_platform_device_remove(struct device *dev) return 0; } -static int of_platform_device_suspend(struct device *dev, pm_message_t state) +static void of_platform_device_shutdown(struct device *dev) { struct of_device *of_dev = to_of_device(dev); struct of_platform_driver *drv = to_of_platform_driver(dev->driver); - int error = 0; - if (dev->driver && drv->suspend) - error = drv->suspend(of_dev, state); - return error; + if (dev->driver && drv->shutdown) + drv->shutdown(of_dev); } -static int of_platform_device_resume(struct device * dev) +#ifdef CONFIG_PM_SLEEP + +static int of_platform_legacy_suspend(struct device *dev, pm_message_t mesg) { struct of_device *of_dev = to_of_device(dev); struct of_platform_driver *drv = to_of_platform_driver(dev->driver); - int error = 0; + int ret = 0; - if (dev->driver && drv->resume) - error = drv->resume(of_dev); - return error; + if (dev->driver && drv->suspend) + ret = drv->suspend(of_dev, mesg); + return ret; } -static void of_platform_device_shutdown(struct device *dev) +static int of_platform_legacy_resume(struct device *dev) { struct of_device *of_dev = to_of_device(dev); struct of_platform_driver *drv = to_of_platform_driver(dev->driver); + int ret = 0; - if (dev->driver && drv->shutdown) - drv->shutdown(of_dev); + if (dev->driver && drv->resume) + ret = drv->resume(of_dev); + return ret; +} + +static int of_platform_pm_prepare(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (drv && drv->pm && drv->pm->prepare) + ret = drv->pm->prepare(dev); + + return ret; +} + +static void of_platform_pm_complete(struct device *dev) +{ + struct device_driver *drv = dev->driver; + + if (drv && drv->pm && drv->pm->complete) + drv->pm->complete(dev); +} + +#ifdef CONFIG_SUSPEND + +static int of_platform_pm_suspend(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->suspend) + ret = drv->pm->suspend(dev); + } else { + ret = of_platform_legacy_suspend(dev, PMSG_SUSPEND); + } + + return ret; } +static int of_platform_pm_suspend_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->suspend_noirq) + ret = drv->pm->suspend_noirq(dev); + } + + return ret; +} + +static int of_platform_pm_resume(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->resume) + ret = drv->pm->resume(dev); + } else { + ret = of_platform_legacy_resume(dev); + } + + return ret; +} + +static int of_platform_pm_resume_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->resume_noirq) + ret = drv->pm->resume_noirq(dev); + } + + return ret; +} + +#else /* !CONFIG_SUSPEND */ + +#define of_platform_pm_suspend NULL +#define of_platform_pm_resume NULL +#define of_platform_pm_suspend_noirq NULL +#define of_platform_pm_resume_noirq NULL + +#endif /* !CONFIG_SUSPEND */ + +#ifdef CONFIG_HIBERNATION + +static int of_platform_pm_freeze(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->freeze) + ret = drv->pm->freeze(dev); + } else { + ret = of_platform_legacy_suspend(dev, PMSG_FREEZE); + } + + return ret; +} + +static int of_platform_pm_freeze_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->freeze_noirq) + ret = drv->pm->freeze_noirq(dev); + } + + return ret; +} + +static int of_platform_pm_thaw(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->thaw) + ret = drv->pm->thaw(dev); + } else { + ret = of_platform_legacy_resume(dev); + } + + return ret; +} + +static int of_platform_pm_thaw_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->thaw_noirq) + ret = drv->pm->thaw_noirq(dev); + } + + return ret; +} + +static int of_platform_pm_poweroff(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->poweroff) + ret = drv->pm->poweroff(dev); + } else { + ret = of_platform_legacy_suspend(dev, PMSG_HIBERNATE); + } + + return ret; +} + +static int of_platform_pm_poweroff_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->poweroff_noirq) + ret = drv->pm->poweroff_noirq(dev); + } + + return ret; +} + +static int of_platform_pm_restore(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->restore) + ret = drv->pm->restore(dev); + } else { + ret = of_platform_legacy_resume(dev); + } + + return ret; +} + +static int of_platform_pm_restore_noirq(struct device *dev) +{ + struct device_driver *drv = dev->driver; + int ret = 0; + + if (!drv) + return 0; + + if (drv->pm) { + if (drv->pm->restore_noirq) + ret = drv->pm->restore_noirq(dev); + } + + return ret; +} + +#else /* !CONFIG_HIBERNATION */ + +#define of_platform_pm_freeze NULL +#define of_platform_pm_thaw NULL +#define of_platform_pm_poweroff NULL +#define of_platform_pm_restore NULL +#define of_platform_pm_freeze_noirq NULL +#define of_platform_pm_thaw_noirq NULL +#define of_platform_pm_poweroff_noirq NULL +#define of_platform_pm_restore_noirq NULL + +#endif /* !CONFIG_HIBERNATION */ + +static struct dev_pm_ops of_platform_dev_pm_ops = { + .prepare = of_platform_pm_prepare, + .complete = of_platform_pm_complete, + .suspend = of_platform_pm_suspend, + .resume = of_platform_pm_resume, + .freeze = of_platform_pm_freeze, + .thaw = of_platform_pm_thaw, + .poweroff = of_platform_pm_poweroff, + .restore = of_platform_pm_restore, + .suspend_noirq = of_platform_pm_suspend_noirq, + .resume_noirq = of_platform_pm_resume_noirq, + .freeze_noirq = of_platform_pm_freeze_noirq, + .thaw_noirq = of_platform_pm_thaw_noirq, + .poweroff_noirq = of_platform_pm_poweroff_noirq, + .restore_noirq = of_platform_pm_restore_noirq, +}; + +#define OF_PLATFORM_PM_OPS_PTR (&of_platform_dev_pm_ops) + +#else /* !CONFIG_PM_SLEEP */ + +#define OF_PLATFORM_PM_OPS_PTR NULL + +#endif /* !CONFIG_PM_SLEEP */ + int of_bus_type_init(struct bus_type *bus, const char *name) { bus->name = name; bus->match = of_platform_bus_match; bus->probe = of_platform_device_probe; bus->remove = of_platform_device_remove; - bus->suspend = of_platform_device_suspend; - bus->resume = of_platform_device_resume; bus->shutdown = of_platform_device_shutdown; bus->dev_attrs = of_platform_device_attrs; + bus->pm = OF_PLATFORM_PM_OPS_PTR; return bus_register(bus); } |