}
 EXPORT_SYMBOL_GPL(of_platform_default_populate);
 
-#ifndef CONFIG_PPC
 static const struct of_device_id reserved_mem_matches[] = {
        { .compatible = "qcom,rmtfs-mem" },
        { .compatible = "qcom,cmd-db" },
        if (!of_have_populated_dt())
                return -ENODEV;
 
-       /*
-        * Handle certain compatibles explicitly, since we don't want to create
-        * platform_devices for every node in /reserved-memory with a
-        * "compatible",
-        */
-       for_each_matching_node(node, reserved_mem_matches)
-               of_platform_device_create(node, NULL, NULL);
+       if (IS_ENABLED(CONFIG_PPC)) {
+               struct device_node *boot_display = NULL;
+               struct platform_device *dev;
+               int ret;
+
+               /* Check if we have a MacOS display without a node spec */
+               if (of_get_property(of_chosen, "linux,bootx-noscreen", NULL)) {
+                       /*
+                        * The old code tried to work out which node was the MacOS
+                        * display based on the address. I'm dropping that since the
+                        * lack of a node spec only happens with old BootX versions
+                        * (users can update) and with this code, they'll still get
+                        * a display (just not the palette hacks).
+                        */
+                       dev = platform_device_alloc("bootx-noscreen", 0);
+                       if (WARN_ON(!dev))
+                               return -ENOMEM;
+                       ret = platform_device_add(dev);
+                       if (WARN_ON(ret)) {
+                               platform_device_put(dev);
+                               return ret;
+                       }
+               }
 
-       node = of_find_node_by_path("/firmware");
-       if (node) {
-               of_platform_populate(node, NULL, NULL, NULL);
-               of_node_put(node);
-       }
+               /*
+                * For OF framebuffers, first create the device for the boot display,
+                * then for the other framebuffers. Only fail for the boot display;
+                * ignore errors for the rest.
+                */
+               for_each_node_by_type(node, "display") {
+                       if (!of_get_property(node, "linux,opened", NULL) ||
+                           !of_get_property(node, "linux,boot-display", NULL))
+                               continue;
+                       dev = of_platform_device_create(node, "of-display", NULL);
+                       if (WARN_ON(!dev))
+                               return -ENOMEM;
+                       boot_display = node;
+                       break;
+               }
+               for_each_node_by_type(node, "display") {
+                       if (!of_get_property(node, "linux,opened", NULL) || node == boot_display)
+                               continue;
+                       of_platform_device_create(node, "of-display", NULL);
+               }
 
-       node = of_get_compatible_child(of_chosen, "simple-framebuffer");
-       of_platform_device_create(node, NULL, NULL);
-       of_node_put(node);
+       } else {
+               /*
+                * Handle certain compatibles explicitly, since we don't want to create
+                * platform_devices for every node in /reserved-memory with a
+                * "compatible",
+                */
+               for_each_matching_node(node, reserved_mem_matches)
+                       of_platform_device_create(node, NULL, NULL);
+
+               node = of_find_node_by_path("/firmware");
+               if (node) {
+                       of_platform_populate(node, NULL, NULL, NULL);
+                       of_node_put(node);
+               }
 
-       /* Populate everything else. */
-       of_platform_default_populate(NULL, NULL, NULL);
+               node = of_get_compatible_child(of_chosen, "simple-framebuffer");
+               of_platform_device_create(node, NULL, NULL);
+               of_node_put(node);
+
+               /* Populate everything else. */
+               of_platform_default_populate(NULL, NULL, NULL);
+       }
 
        return 0;
 }
        return 0;
 }
 late_initcall_sync(of_platform_sync_state_init);
-#endif
 
 int of_platform_device_destroy(struct device *dev, void *data)
 {
 
                FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
 }
 
-static void __init offb_init_fb(const char *name,
-                               int width, int height, int depth,
-                               int pitch, unsigned long address,
-                               int foreign_endian, struct device_node *dp)
+static void offb_init_fb(struct platform_device *parent, const char *name,
+                        int width, int height, int depth,
+                        int pitch, unsigned long address,
+                        int foreign_endian, struct device_node *dp)
 {
        unsigned long res_size = pitch * height;
        struct offb_par *par = &default_par;
                return;
        }
 
-       info = framebuffer_alloc(sizeof(u32) * 16, NULL);
+       info = framebuffer_alloc(sizeof(u32) * 16, &parent->dev);
 
        if (!info) {
                release_mem_region(res_start, res_size);
                return;
        }
+       platform_set_drvdata(parent, info);
 
        fix = &info->fix;
        var = &info->var;
 }
 
 
-static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
+static void offb_init_nodriver(struct platform_device *parent, struct device_node *dp,
+                              int no_real_node)
 {
        unsigned int len;
        int i, width = 640, height = 480, depth = 8, pitch = 640;
                /* kludge for valkyrie */
                if (of_node_name_eq(dp, "valkyrie"))
                        address += 0x1000;
-               offb_init_fb(no_real_node ? "bootx" : NULL,
+               offb_init_fb(parent, no_real_node ? "bootx" : NULL,
                             width, height, depth, pitch, address,
                             foreign_endian, no_real_node ? NULL : dp);
        }
 }
 
-static int __init offb_init(void)
+static int offb_remove(struct platform_device *pdev)
 {
-       struct device_node *dp = NULL, *boot_disp = NULL;
+       struct fb_info *info = platform_get_drvdata(pdev);
 
-       if (fb_get_options("offb", NULL))
-               return -ENODEV;
+       if (info)
+               unregister_framebuffer(info);
 
-       /* Check if we have a MacOS display without a node spec */
-       if (of_get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) {
-               /* The old code tried to work out which node was the MacOS
-                * display based on the address. I'm dropping that since the
-                * lack of a node spec only happens with old BootX versions
-                * (users can update) and with this code, they'll still get
-                * a display (just not the palette hacks).
-                */
-               offb_init_nodriver(of_chosen, 1);
-       }
+       return 0;
+}
 
-       for_each_node_by_type(dp, "display") {
-               if (of_get_property(dp, "linux,opened", NULL) &&
-                   of_get_property(dp, "linux,boot-display", NULL)) {
-                       boot_disp = dp;
-                       offb_init_nodriver(dp, 0);
-               }
-       }
-       for_each_node_by_type(dp, "display") {
-               if (of_get_property(dp, "linux,opened", NULL) &&
-                   dp != boot_disp)
-                       offb_init_nodriver(dp, 0);
-       }
+static int offb_probe_bootx_noscreen(struct platform_device *pdev)
+{
+       offb_init_nodriver(pdev, of_chosen, 1);
 
        return 0;
 }
 
+static struct platform_driver offb_driver_bootx_noscreen = {
+       .driver = {
+               .name = "bootx-noscreen",
+       },
+       .probe = offb_probe_bootx_noscreen,
+       .remove = offb_remove,
+};
+
+static int offb_probe_display(struct platform_device *pdev)
+{
+       offb_init_nodriver(pdev, pdev->dev.of_node, 0);
+
+       return 0;
+}
 
+static const struct of_device_id offb_of_match_display[] = {
+       { .compatible = "display", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, offb_of_match_display);
+
+static struct platform_driver offb_driver_display = {
+       .driver = {
+               .name = "of-display",
+               .of_match_table = offb_of_match_display,
+       },
+       .probe = offb_probe_display,
+       .remove = offb_remove,
+};
+
+static int __init offb_init(void)
+{
+       if (fb_get_options("offb", NULL))
+               return -ENODEV;
+
+       platform_driver_register(&offb_driver_bootx_noscreen);
+       platform_driver_register(&offb_driver_display);
+
+       return 0;
+}
 module_init(offb_init);
+
+static void __exit offb_exit(void)
+{
+       platform_driver_unregister(&offb_driver_display);
+       platform_driver_unregister(&offb_driver_bootx_noscreen);
+}
+module_exit(offb_exit);
+
 MODULE_LICENSE("GPL");