Merge git://git.infradead.org/battery-2.6
[deliverable/linux.git] / arch / powerpc / kernel / ibmebus.c
index f62efdfd176989c142019351fe691b52edc5260f..c00d4ca1ee157fc995629825b95af4b8b232a5bb 100644 (file)
@@ -201,13 +201,14 @@ int ibmebus_register_driver(struct of_platform_driver *drv)
        /* If the driver uses devices that ibmebus doesn't know, add them */
        ibmebus_create_devices(drv->driver.of_match_table);
 
-       return of_register_driver(drv, &ibmebus_bus_type);
+       drv->driver.bus = &ibmebus_bus_type;
+       return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_register_driver);
 
 void ibmebus_unregister_driver(struct of_platform_driver *drv)
 {
-       of_unregister_driver(drv);
+       driver_unregister(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_unregister_driver);
 
@@ -308,15 +309,410 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
        }
 }
 
+
 static struct bus_attribute ibmebus_bus_attrs[] = {
        __ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe),
        __ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove),
        __ATTR_NULL
 };
 
+static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv)
+{
+       const struct of_device_id *matches = drv->of_match_table;
+
+       if (!matches)
+               return 0;
+
+       return of_match_device(matches, dev) != NULL;
+}
+
+static int ibmebus_bus_device_probe(struct device *dev)
+{
+       int error = -ENODEV;
+       struct of_platform_driver *drv;
+       struct platform_device *of_dev;
+       const struct of_device_id *match;
+
+       drv = to_of_platform_driver(dev->driver);
+       of_dev = to_platform_device(dev);
+
+       if (!drv->probe)
+               return error;
+
+       of_dev_get(of_dev);
+
+       match = of_match_device(drv->driver.of_match_table, dev);
+       if (match)
+               error = drv->probe(of_dev, match);
+       if (error)
+               of_dev_put(of_dev);
+
+       return error;
+}
+
+static int ibmebus_bus_device_remove(struct device *dev)
+{
+       struct platform_device *of_dev = to_platform_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 ibmebus_bus_device_shutdown(struct device *dev)
+{
+       struct platform_device *of_dev = to_platform_device(dev);
+       struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+
+       if (dev->driver && drv->shutdown)
+               drv->shutdown(of_dev);
+}
+
+/*
+ * ibmebus_bus_device_attrs
+ */
+static ssize_t devspec_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct platform_device *ofdev;
+
+       ofdev = to_platform_device(dev);
+       return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name);
+}
+
+static ssize_t name_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct platform_device *ofdev;
+
+       ofdev = to_platform_device(dev);
+       return sprintf(buf, "%s\n", ofdev->dev.of_node->name);
+}
+
+static ssize_t modalias_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
+       buf[len] = '\n';
+       buf[len+1] = 0;
+       return len+1;
+}
+
+struct device_attribute ibmebus_bus_device_attrs[] = {
+       __ATTR_RO(devspec),
+       __ATTR_RO(name),
+       __ATTR_RO(modalias),
+       __ATTR_NULL
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int ibmebus_bus_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+       struct platform_device *of_dev = to_platform_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 ibmebus_bus_legacy_resume(struct device *dev)
+{
+       struct platform_device *of_dev = to_platform_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 ibmebus_bus_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 ibmebus_bus_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 ibmebus_bus_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 = ibmebus_bus_legacy_suspend(dev, PMSG_SUSPEND);
+       }
+
+       return ret;
+}
+
+static int ibmebus_bus_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 ibmebus_bus_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 = ibmebus_bus_legacy_resume(dev);
+       }
+
+       return ret;
+}
+
+static int ibmebus_bus_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 ibmebus_bus_pm_suspend         NULL
+#define ibmebus_bus_pm_resume          NULL
+#define ibmebus_bus_pm_suspend_noirq   NULL
+#define ibmebus_bus_pm_resume_noirq    NULL
+
+#endif /* !CONFIG_SUSPEND */
+
+#ifdef CONFIG_HIBERNATION
+
+static int ibmebus_bus_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 = ibmebus_bus_legacy_suspend(dev, PMSG_FREEZE);
+       }
+
+       return ret;
+}
+
+static int ibmebus_bus_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 ibmebus_bus_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 = ibmebus_bus_legacy_resume(dev);
+       }
+
+       return ret;
+}
+
+static int ibmebus_bus_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 ibmebus_bus_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 = ibmebus_bus_legacy_suspend(dev, PMSG_HIBERNATE);
+       }
+
+       return ret;
+}
+
+static int ibmebus_bus_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 ibmebus_bus_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 = ibmebus_bus_legacy_resume(dev);
+       }
+
+       return ret;
+}
+
+static int ibmebus_bus_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 ibmebus_bus_pm_freeze          NULL
+#define ibmebus_bus_pm_thaw            NULL
+#define ibmebus_bus_pm_poweroff                NULL
+#define ibmebus_bus_pm_restore         NULL
+#define ibmebus_bus_pm_freeze_noirq    NULL
+#define ibmebus_bus_pm_thaw_noirq              NULL
+#define ibmebus_bus_pm_poweroff_noirq  NULL
+#define ibmebus_bus_pm_restore_noirq   NULL
+
+#endif /* !CONFIG_HIBERNATION */
+
+static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
+       .prepare = ibmebus_bus_pm_prepare,
+       .complete = ibmebus_bus_pm_complete,
+       .suspend = ibmebus_bus_pm_suspend,
+       .resume = ibmebus_bus_pm_resume,
+       .freeze = ibmebus_bus_pm_freeze,
+       .thaw = ibmebus_bus_pm_thaw,
+       .poweroff = ibmebus_bus_pm_poweroff,
+       .restore = ibmebus_bus_pm_restore,
+       .suspend_noirq = ibmebus_bus_pm_suspend_noirq,
+       .resume_noirq = ibmebus_bus_pm_resume_noirq,
+       .freeze_noirq = ibmebus_bus_pm_freeze_noirq,
+       .thaw_noirq = ibmebus_bus_pm_thaw_noirq,
+       .poweroff_noirq = ibmebus_bus_pm_poweroff_noirq,
+       .restore_noirq = ibmebus_bus_pm_restore_noirq,
+};
+
+#define IBMEBUS_BUS_PM_OPS_PTR (&ibmebus_bus_dev_pm_ops)
+
+#else /* !CONFIG_PM_SLEEP */
+
+#define IBMEBUS_BUS_PM_OPS_PTR NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
 struct bus_type ibmebus_bus_type = {
+       .name      = "ibmebus",
        .uevent    = of_device_uevent,
-       .bus_attrs = ibmebus_bus_attrs
+       .bus_attrs = ibmebus_bus_attrs,
+       .match     = ibmebus_bus_bus_match,
+       .probe     = ibmebus_bus_device_probe,
+       .remove    = ibmebus_bus_device_remove,
+       .shutdown  = ibmebus_bus_device_shutdown,
+       .dev_attrs = ibmebus_bus_device_attrs,
+       .pm        = IBMEBUS_BUS_PM_OPS_PTR,
 };
 EXPORT_SYMBOL(ibmebus_bus_type);
 
@@ -326,7 +722,7 @@ static int __init ibmebus_bus_init(void)
 
        printk(KERN_INFO "IBM eBus Device Driver\n");
 
-       err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
+       err = bus_register(&ibmebus_bus_type);
        if (err) {
                printk(KERN_ERR "%s: failed to register IBM eBus.\n",
                       __func__);
This page took 0.027674 seconds and 5 git commands to generate.