]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/base/platform.c
drivers/video/fbmem.c: simplify strlen()==0 check in fb_get_options()
[karo-tx-linux.git] / drivers / base / platform.c
index 4d99c8bdfedcd8f062c9e7924e0698cf692b81de..c6c933f58102370d8ed738e2778cb11dad2e93fb 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/string.h>
 #include <linux/platform_device.h>
+#include <linux/of_device.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
@@ -191,13 +192,13 @@ int platform_device_add_resources(struct platform_device *pdev,
 {
        struct resource *r;
 
-       r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL);
+       r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
        if (r) {
-               memcpy(r, res, sizeof(struct resource) * num);
                pdev->resource = r;
                pdev->num_resources = num;
+               return 0;
        }
-       return r ? 0 : -ENOMEM;
+       return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(platform_device_add_resources);
 
@@ -344,108 +345,56 @@ void platform_device_unregister(struct platform_device *pdev)
 EXPORT_SYMBOL_GPL(platform_device_unregister);
 
 /**
- * platform_device_register_simple - add a platform-level device and its resources
- * @name: base name of the device we're adding
- * @id: instance id
- * @res: set of resources that needs to be allocated for the device
- * @num: number of resources
+ * platform_device_register_resndata - add a platform-level device with
+ * resources and platform-specific data
  *
- * This function creates a simple platform device that requires minimal
- * resource and memory management. Canned release function freeing memory
- * allocated for the device allows drivers using such devices to be
- * unloaded without waiting for the last reference to the device to be
- * dropped.
- *
- * This interface is primarily intended for use with legacy drivers which
- * probe hardware directly.  Because such drivers create sysfs device nodes
- * themselves, rather than letting system infrastructure handle such device
- * enumeration tasks, they don't fully conform to the Linux driver model.
- * In particular, when such drivers are built as modules, they can't be
- * "hotplugged".
- *
- * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
- */
-struct platform_device *platform_device_register_simple(const char *name,
-                                                       int id,
-                                                       const struct resource *res,
-                                                       unsigned int num)
-{
-       struct platform_device *pdev;
-       int retval;
-
-       pdev = platform_device_alloc(name, id);
-       if (!pdev) {
-               retval = -ENOMEM;
-               goto error;
-       }
-
-       if (num) {
-               retval = platform_device_add_resources(pdev, res, num);
-               if (retval)
-                       goto error;
-       }
-
-       retval = platform_device_add(pdev);
-       if (retval)
-               goto error;
-
-       return pdev;
-
-error:
-       platform_device_put(pdev);
-       return ERR_PTR(retval);
-}
-EXPORT_SYMBOL_GPL(platform_device_register_simple);
-
-/**
- * platform_device_register_data - add a platform-level device with platform-specific data
  * @parent: parent device for the device we're adding
  * @name: base name of the device we're adding
  * @id: instance id
+ * @res: set of resources that needs to be allocated for the device
+ * @num: number of resources
  * @data: platform specific data for this platform device
  * @size: size of platform specific data
  *
- * This function creates a simple platform device that requires minimal
- * resource and memory management. Canned release function freeing memory
- * allocated for the device allows drivers using such devices to be
- * unloaded without waiting for the last reference to the device to be
- * dropped.
- *
  * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
  */
-struct platform_device *platform_device_register_data(
+struct platform_device *__init_or_module platform_device_register_resndata(
                struct device *parent,
                const char *name, int id,
+               const struct resource *res, unsigned int num,
                const void *data, size_t size)
 {
+       int ret = -ENOMEM;
        struct platform_device *pdev;
-       int retval;
 
        pdev = platform_device_alloc(name, id);
-       if (!pdev) {
-               retval = -ENOMEM;
-               goto error;
-       }
+       if (!pdev)
+               goto err;
 
        pdev->dev.parent = parent;
 
-       if (size) {
-               retval = platform_device_add_data(pdev, data, size);
-               if (retval)
-                       goto error;
+       if (res) {
+               ret = platform_device_add_resources(pdev, res, num);
+               if (ret)
+                       goto err;
        }
 
-       retval = platform_device_add(pdev);
-       if (retval)
-               goto error;
+       if (data) {
+               ret = platform_device_add_data(pdev, data, size);
+               if (ret)
+                       goto err;
+       }
 
-       return pdev;
+       ret = platform_device_add(pdev);
+       if (ret) {
+err:
+               platform_device_put(pdev);
+               return ERR_PTR(ret);
+       }
 
-error:
-       platform_device_put(pdev);
-       return ERR_PTR(retval);
+       return pdev;
 }
-EXPORT_SYMBOL_GPL(platform_device_register_data);
+EXPORT_SYMBOL_GPL(platform_device_register_resndata);
 
 static int platform_drv_probe(struct device *_dev)
 {
@@ -635,6 +584,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);
@@ -673,7 +628,11 @@ static int platform_match(struct device *dev, struct device_driver *drv)
        struct platform_device *pdev = to_platform_device(dev);
        struct platform_driver *pdrv = to_platform_driver(drv);
 
-       /* match against the id table first */
+       /* Attempt an OF style match first */
+       if (of_driver_match_device(dev, drv))
+               return 1;
+
+       /* Then try to match against the id table */
        if (pdrv->id_table)
                return platform_match_id(pdrv->id_table, pdev) != NULL;