of: Merge of_platform_bus_type with platform_bus_type
authorGrant Likely <grant.likely@secretlab.ca>
Tue, 8 Jun 2010 13:48:21 +0000 (07:48 -0600)
committerGrant Likely <grant.likely@secretlab.ca>
Sat, 24 Jul 2010 15:57:51 +0000 (09:57 -0600)
of_platform_bus was being used in the same manner as the platform_bus.
The only difference being that of_platform_bus devices are generated
from data in the device tree, and platform_bus devices are usually
statically allocated in platform code.  Having them separate causes
the problem of device drivers having to be registered twice if it
was possible for the same device to appear on either bus.

This patch removes of_platform_bus_type and registers all of_platform
bus devices and drivers on the platform bus instead.  A previous patch
made the of_device structure an alias for the platform_device structure,
and a shim is used to adapt of_platform_drivers to the platform bus.

After all of of_platform_bus drivers are converted to be normal platform
drivers, the shim code can be removed.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: David S. Miller <davem@davemloft.net>
16 files changed:
arch/microblaze/kernel/of_platform.c
arch/microblaze/kernel/setup.c
arch/powerpc/kernel/dma-swiotlb.c
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/platforms/cell/beat_iommu.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/sysdev/mv64x60_dev.c
arch/sparc/kernel/of_device_32.c
arch/sparc/kernel/of_device_64.c
arch/sparc/kernel/of_device_common.c
drivers/base/platform.c
drivers/of/device.c
drivers/of/platform.c
include/linux/of_device.h
include/linux/of_platform.h

index da79edf454208340a615a466fcb36cc9eceaad84..fb28661043311fcdaf5f9a838af1b902922082f6 100644 (file)
 #include <linux/topology.h>
 #include <asm/atomic.h>
 
-struct bus_type of_platform_bus_type = {
-       .uevent = of_device_uevent,
-};
-EXPORT_SYMBOL(of_platform_bus_type);
-
-static int __init of_bus_driver_init(void)
-{
-       return of_bus_type_init(&of_platform_bus_type, "of_platform");
-}
-postcore_initcall(of_bus_driver_init);
-
 /*
  * The list of OF IDs below is used for matching bus types in the
  * system whose devices are to be exposed as of_platform_devices.
index 17c98dbcec888f698e2c038eee317ddef7e1f7da..f5f768842354201266bf0dce0e7209484f49a4fa 100644 (file)
@@ -213,15 +213,9 @@ static struct notifier_block dflt_plat_bus_notifier = {
        .priority = INT_MAX,
 };
 
-static struct notifier_block dflt_of_bus_notifier = {
-       .notifier_call = dflt_bus_notify,
-       .priority = INT_MAX,
-};
-
 static int __init setup_bus_notifier(void)
 {
        bus_register_notifier(&platform_bus_type, &dflt_plat_bus_notifier);
-       bus_register_notifier(&of_platform_bus_type, &dflt_of_bus_notifier);
 
        return 0;
 }
index 02f724f367533ee60f6512a7453cb0f0e3024fbc..4295e0b94b2db31238f008c49756955fd4922702 100644 (file)
@@ -82,17 +82,9 @@ static struct notifier_block ppc_swiotlb_plat_bus_notifier = {
        .priority = 0,
 };
 
-static struct notifier_block ppc_swiotlb_of_bus_notifier = {
-       .notifier_call = ppc_swiotlb_bus_notify,
-       .priority = 0,
-};
-
 int __init swiotlb_setup_bus_notifier(void)
 {
        bus_register_notifier(&platform_bus_type,
                              &ppc_swiotlb_plat_bus_notifier);
-       bus_register_notifier(&of_platform_bus_type,
-                             &ppc_swiotlb_of_bus_notifier);
-
        return 0;
 }
index 4e0a2f7c1dd37b6791ca682be4d4b02b21a4ac8b..d3497cd81e8a86bb79c9230c3cd5cab693c79c07 100644 (file)
@@ -52,18 +52,6 @@ const struct of_device_id of_default_bus_ids[] = {
        {},
 };
 
-struct bus_type of_platform_bus_type = {
-       .uevent = of_device_uevent,
-};
-EXPORT_SYMBOL(of_platform_bus_type);
-
-static int __init of_bus_driver_init(void)
-{
-       return of_bus_type_init(&of_platform_bus_type, "of_platform");
-}
-
-postcore_initcall(of_bus_driver_init);
-
 static int of_dev_node_match(struct device *dev, void *data)
 {
        return to_of_device(dev)->dev.of_node == data;
index b7e6c7e193ae9141cc0aa6b1c7beb3394240c937..d1a5304b3dddad851478c2c03c2528bd844ff175 100644 (file)
@@ -701,16 +701,9 @@ static struct notifier_block ppc_dflt_plat_bus_notifier = {
        .priority = INT_MAX,
 };
 
-static struct notifier_block ppc_dflt_of_bus_notifier = {
-       .notifier_call = ppc_dflt_bus_notify,
-       .priority = INT_MAX,
-};
-
 static int __init setup_bus_notifier(void)
 {
        bus_register_notifier(&platform_bus_type, &ppc_dflt_plat_bus_notifier);
-       bus_register_notifier(&of_platform_bus_type, &ppc_dflt_of_bus_notifier);
-
        return 0;
 }
 
index 39d361c5c6d2e73d4ca9f37d1c415b871ca30610..beec405eb6f8d47142959427e6ef97f9f08bc88c 100644 (file)
@@ -108,7 +108,7 @@ static int __init celleb_init_iommu(void)
        celleb_init_direct_mapping();
        set_pci_dma_ops(&dma_direct_ops);
        ppc_md.pci_dma_dev_setup = celleb_pci_dma_dev_setup;
-       bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier);
+       bus_register_notifier(&platform_bus_type, &celleb_of_bus_notifier);
 
        return 0;
 }
index 3712900471ba2e9033419ab31d620ab8d2a983b2..58b13ce3847ec3c92453ef70d5ec4e653d6d886a 100644 (file)
@@ -1204,7 +1204,7 @@ static int __init cell_iommu_init(void)
        /* Register callbacks on OF platform device addition/removal
         * to handle linking them to the right DMA operations
         */
-       bus_register_notifier(&of_platform_bus_type, &cell_of_bus_notifier);
+       bus_register_notifier(&platform_bus_type, &cell_of_bus_notifier);
 
        return 0;
 }
index 31acd3b1718b8f09be498fd2a15d82aa72464ca5..1398bc454999b2b10fae54972e5e92c69689b3eb 100644 (file)
 
 #include <asm/prom.h>
 
-/*
- * These functions provide the necessary setup for the mv64x60 drivers.
- * These drivers are unusual in that they work on both the MIPS and PowerPC
- * architectures.  Because of that, the drivers do not support the normal
- * PowerPC of_platform_bus_type.  They support platform_bus_type instead.
- */
+/* These functions provide the necessary setup for the mv64x60 drivers. */
 
 static struct of_device_id __initdata of_mv64x60_devices[] = {
        { .compatible = "marvell,mv64306-devctrl", },
index 331de91ad2bcb290c542ade8f1dd495e458279cf..75fc9d5cd7e61069d73e198a86ee570cb399cf4a 100644 (file)
@@ -424,7 +424,7 @@ build_resources:
        build_device_resources(op, parent);
 
        op->dev.parent = parent;
-       op->dev.bus = &of_platform_bus_type;
+       op->dev.bus = &platform_bus_type;
        if (!parent)
                dev_set_name(&op->dev, "root");
        else
@@ -452,30 +452,19 @@ static void __init scan_tree(struct device_node *dp, struct device *parent)
        }
 }
 
-static void __init scan_of_devices(void)
+static int __init scan_of_devices(void)
 {
        struct device_node *root = of_find_node_by_path("/");
        struct of_device *parent;
 
        parent = scan_one_device(root, NULL);
        if (!parent)
-               return;
+               return 0;
 
        scan_tree(root->child, &parent->dev);
+       return 0;
 }
-
-static int __init of_bus_driver_init(void)
-{
-       int err;
-
-       err = of_bus_type_init(&of_platform_bus_type, "of");
-       if (!err)
-               scan_of_devices();
-
-       return err;
-}
-
-postcore_initcall(of_bus_driver_init);
+postcore_initcall(scan_of_devices);
 
 static int __init of_debug(char *str)
 {
index 5e8cbb942d3dc0b4bf6c1c7d118b4d8226c65f53..9743d1d9fa03fc06d89c33f86bf5d06c40ed404d 100644 (file)
@@ -667,7 +667,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
                op->archdata.irqs[i] = build_one_device_irq(op, parent, op->archdata.irqs[i]);
 
        op->dev.parent = parent;
-       op->dev.bus = &of_platform_bus_type;
+       op->dev.bus = &platform_bus_type;
        if (!parent)
                dev_set_name(&op->dev, "root");
        else
@@ -695,30 +695,19 @@ static void __init scan_tree(struct device_node *dp, struct device *parent)
        }
 }
 
-static void __init scan_of_devices(void)
+static int __init scan_of_devices(void)
 {
        struct device_node *root = of_find_node_by_path("/");
        struct of_device *parent;
 
        parent = scan_one_device(root, NULL);
        if (!parent)
-               return;
+               return 0;
 
        scan_tree(root->child, &parent->dev);
+       return 0;
 }
-
-static int __init of_bus_driver_init(void)
-{
-       int err;
-
-       err = of_bus_type_init(&of_platform_bus_type, "of");
-       if (!err)
-               scan_of_devices();
-
-       return err;
-}
-
-postcore_initcall(of_bus_driver_init);
+postcore_initcall(scan_of_devices);
 
 static int __init of_debug(char *str)
 {
index 016c947d4cae69786332432ce9735f374a4c2f50..01f380c7995cdaefcb93c7572d9d4787a432e7b4 100644 (file)
@@ -64,9 +64,6 @@ void of_propagate_archdata(struct of_device *bus)
        }
 }
 
-struct bus_type of_platform_bus_type;
-EXPORT_SYMBOL(of_platform_bus_type);
-
 static void get_cells(struct device_node *dp, int *addrc, int *sizec)
 {
        if (addrc)
index fac3633c72235837fa2ab694967523d3ced5e76c..f699fabf403bedd931fd457a2c200faef58ad7ea 100644 (file)
@@ -636,6 +636,12 @@ static struct device_attribute platform_dev_attrs[] = {
 static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        struct platform_device  *pdev = to_platform_device(dev);
+       int rc;
+
+       /* Some devices have extra OF data and an OF-style MODALIAS */
+       rc = of_device_uevent(dev,env);
+       if (rc != -ENODEV)
+               return rc;
 
        add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
                (pdev->id_entry) ? pdev->id_entry->name : pdev->name);
index 5282a202f5a95533cca53e1ab0e227700979b6cd..12a44b493511e5a3599f0fe1c80a14d755aea3aa 100644 (file)
@@ -104,6 +104,11 @@ int of_device_register(struct of_device *ofdev)
 
        device_initialize(&ofdev->dev);
 
+       /* name and id have to be set so that the platform bus doesn't get
+        * confused on matching */
+       ofdev->name = dev_name(&ofdev->dev);
+       ofdev->id = -1;
+
        /* device_add will assume that this device is on the same node as
         * the parent. If there is no parent defined, set the node
         * explicitly */
index 9d3d932bcb6fa50759c0eb3f4dbd8414a6dbe886..712dfd866df09e0bc73aecfddab1410a886ea387 100644 (file)
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+static int platform_driver_probe_shim(struct platform_device *pdev)
+{
+       struct platform_driver *pdrv;
+       struct of_platform_driver *ofpdrv;
+       const struct of_device_id *match;
+
+       pdrv = container_of(pdev->dev.driver, struct platform_driver, driver);
+       ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver);
+       match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
+       return ofpdrv->probe(pdev, match);
+}
+
+static void platform_driver_shutdown_shim(struct platform_device *pdev)
+{
+       struct platform_driver *pdrv;
+       struct of_platform_driver *ofpdrv;
+
+       pdrv = container_of(pdev->dev.driver, struct platform_driver, driver);
+       ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver);
+       ofpdrv->shutdown(pdev);
+}
+
+/**
+ * of_register_platform_driver
+ */
+int of_register_platform_driver(struct of_platform_driver *drv)
+{
+       /* setup of_platform_driver to platform_driver adaptors */
+       drv->platform_driver.driver = drv->driver;
+       if (drv->probe)
+               drv->platform_driver.probe = platform_driver_probe_shim;
+       drv->platform_driver.remove = drv->remove;
+       if (drv->shutdown)
+               drv->platform_driver.shutdown = platform_driver_shutdown_shim;
+       drv->platform_driver.suspend = drv->suspend;
+       drv->platform_driver.resume = drv->resume;
+
+       return platform_driver_register(&drv->platform_driver);
+}
+EXPORT_SYMBOL(of_register_platform_driver);
+
+void of_unregister_platform_driver(struct of_platform_driver *drv)
+{
+       platform_driver_unregister(&drv->platform_driver);
+}
+EXPORT_SYMBOL(of_unregister_platform_driver);
 
 #if defined(CONFIG_PPC_DCR)
 #include <asm/dcr.h>
@@ -392,16 +440,29 @@ int of_bus_type_init(struct bus_type *bus, const char *name)
 
 int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
 {
-       drv->driver.bus = bus;
+       /*
+        * Temporary: of_platform_bus used to be distinct from the platform
+        * bus.  It isn't anymore, and so drivers on the platform bus need
+        * to be registered in a special way.
+        *
+        * After all of_platform_bus_type drivers are converted to
+        * platform_drivers, this exception can be removed.
+        */
+       if (bus == &platform_bus_type)
+               return of_register_platform_driver(drv);
 
        /* register with core */
+       drv->driver.bus = bus;
        return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL(of_register_driver);
 
 void of_unregister_driver(struct of_platform_driver *drv)
 {
-       driver_unregister(&drv->driver);
+       if (drv->driver.bus == &platform_bus_type)
+               of_unregister_platform_driver(drv);
+       else
+               driver_unregister(&drv->driver);
 }
 EXPORT_SYMBOL(of_unregister_driver);
 
@@ -548,7 +609,7 @@ struct of_device *of_platform_device_create(struct device_node *np,
        dev->archdata.dma_mask = 0xffffffffUL;
 #endif
        dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-       dev->dev.bus = &of_platform_bus_type;
+       dev->dev.bus = &platform_bus_type;
 
        /* We do not fill the DMA ops for platform devices by default.
         * This is currently the responsibility of the platform code
index 7d27f5a878f604c850fd5f323f321cf289c88129..8cd1fe7864e33bbfad9ad374aa1df2baefa94fc9 100644 (file)
@@ -65,6 +65,12 @@ static inline int of_driver_match_device(struct device *dev,
        return 0;
 }
 
+static inline int of_device_uevent(struct device *dev,
+                                  struct kobj_uevent_env *env)
+{
+       return -ENODEV;
+}
+
 #endif /* CONFIG_OF_DEVICE */
 
 #endif /* _LINUX_OF_DEVICE_H */
index a51fd30176aaba3e8bd2c751615a23ff17fd5c3e..133ecf31a60f3dac79f8f93ce8659e94dc9705d7 100644 (file)
 #include <linux/mod_devicetable.h>
 #include <linux/pm.h>
 #include <linux/of_device.h>
+#include <linux/platform_device.h>
 
 /*
- * The of_platform_bus_type is a bus type used by drivers that do not
- * attach to a macio or similar bus but still use OF probing
- * mechanism
+ * of_platform_bus_type isn't it's own bus anymore.  It's now just an alias
+ * for the platform bus.
  */
-extern struct bus_type of_platform_bus_type;
+#define of_platform_bus_type platform_bus_type
 
 extern const struct of_device_id of_default_bus_ids[];
 
 /*
  * An of_platform_driver driver is attached to a basic of_device on
- * the "platform bus" (of_platform_bus_type).
+ * the "platform bus" (platform_bus_type).
  */
 struct of_platform_driver
 {
@@ -42,6 +42,7 @@ struct of_platform_driver
        int     (*shutdown)(struct of_device* dev);
 
        struct device_driver    driver;
+       struct platform_driver  platform_driver;
 };
 #define        to_of_platform_driver(drv) \
        container_of(drv,struct of_platform_driver, driver)
@@ -51,14 +52,8 @@ extern int of_register_driver(struct of_platform_driver *drv,
 extern void of_unregister_driver(struct of_platform_driver *drv);
 
 /* Platform drivers register/unregister */
-static inline int of_register_platform_driver(struct of_platform_driver *drv)
-{
-       return of_register_driver(drv, &of_platform_bus_type);
-}
-static inline void of_unregister_platform_driver(struct of_platform_driver *drv)
-{
-       of_unregister_driver(drv);
-}
+extern int of_register_platform_driver(struct of_platform_driver *drv);
+extern void of_unregister_platform_driver(struct of_platform_driver *drv);
 
 extern struct of_device *of_device_alloc(struct device_node *np,
                                         const char *bus_id,