123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- /*
- * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
- * <benh@kernel.crashing.org>
- * and Arnd Bergmann, IBM Corp.
- * Merged from powerpc/kernel/of_platform.c and
- * sparc{,64}/kernel/of_device.c by Stephen Rothwell
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
- #include <linux/errno.h>
- #include <linux/module.h>
- #include <linux/device.h>
- #include <linux/of_device.h>
- #include <linux/of_platform.h>
- extern struct device_attribute of_platform_device_attrs[];
- static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
- {
- struct of_device *of_dev = to_of_device(dev);
- struct of_platform_driver *of_drv = to_of_platform_driver(drv);
- const struct of_device_id *matches = of_drv->match_table;
- if (!matches)
- return 0;
- return of_match_device(matches, of_dev) != NULL;
- }
- static int of_platform_device_probe(struct device *dev)
- {
- int error = -ENODEV;
- struct of_platform_driver *drv;
- struct of_device *of_dev;
- const struct of_device_id *match;
- drv = to_of_platform_driver(dev->driver);
- of_dev = to_of_device(dev);
- if (!drv->probe)
- return error;
- of_dev_get(of_dev);
- match = of_match_device(drv->match_table, of_dev);
- if (match)
- error = drv->probe(of_dev, match);
- if (error)
- of_dev_put(of_dev);
- return error;
- }
- static int of_platform_device_remove(struct device *dev)
- {
- struct of_device *of_dev = to_of_device(dev);
- struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
- if (dev->driver && drv->remove)
- drv->remove(of_dev);
- return 0;
- }
- 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);
- if (dev->driver && drv->shutdown)
- drv->shutdown(of_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 ret = 0;
- if (dev->driver && drv->suspend)
- ret = drv->suspend(of_dev, mesg);
- return ret;
- }
- 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->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->shutdown = of_platform_device_shutdown;
- bus->dev_attrs = of_platform_device_attrs;
- bus->pm = OF_PLATFORM_PM_OPS_PTR;
- return bus_register(bus);
- }
- int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
- {
- /* initialize common driver fields */
- if (!drv->driver.name)
- drv->driver.name = drv->name;
- if (!drv->driver.owner)
- drv->driver.owner = drv->owner;
- drv->driver.bus = bus;
- /* register with core */
- return driver_register(&drv->driver);
- }
- EXPORT_SYMBOL(of_register_driver);
- void of_unregister_driver(struct of_platform_driver *drv)
- {
- driver_unregister(&drv->driver);
- }
- EXPORT_SYMBOL(of_unregister_driver);
|