]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/of/device.c
lib/decompress_bunzip2.c: fix checkstack warning
[karo-tx-linux.git] / drivers / of / device.c
index 7d18f8e0b013199c2e1bfd886b8dd6b93c639f7e..0d8a0644f54018810129479244c975be57f2c34c 100644 (file)
 const struct of_device_id *of_match_device(const struct of_device_id *matches,
                                           const struct device *dev)
 {
-       if (!dev->of_node)
+       if ((!matches) || (!dev->of_node))
                return NULL;
        return of_match_node(matches, dev->of_node);
 }
 EXPORT_SYMBOL(of_match_device);
 
-struct of_device *of_dev_get(struct of_device *dev)
+struct platform_device *of_dev_get(struct platform_device *dev)
 {
        struct device *tmp;
 
@@ -34,13 +34,13 @@ struct of_device *of_dev_get(struct of_device *dev)
                return NULL;
        tmp = get_device(&dev->dev);
        if (tmp)
-               return to_of_device(tmp);
+               return to_platform_device(tmp);
        else
                return NULL;
 }
 EXPORT_SYMBOL(of_dev_get);
 
-void of_dev_put(struct of_device *dev)
+void of_dev_put(struct platform_device *dev)
 {
        if (dev)
                put_device(&dev->dev);
@@ -50,28 +50,25 @@ EXPORT_SYMBOL(of_dev_put);
 static ssize_t devspec_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct of_device *ofdev;
+       struct platform_device *ofdev;
 
-       ofdev = to_of_device(dev);
+       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 of_device *ofdev;
+       struct platform_device *ofdev;
 
-       ofdev = to_of_device(dev);
+       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)
 {
-       struct of_device *ofdev = to_of_device(dev);
-       ssize_t len = 0;
-
-       len = of_device_get_modalias(ofdev, buf, PAGE_SIZE - 2);
+       ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
        buf[len] = '\n';
        buf[len+1] = 0;
        return len+1;
@@ -93,20 +90,25 @@ struct device_attribute of_platform_device_attrs[] = {
  */
 void of_release_dev(struct device *dev)
 {
-       struct of_device *ofdev;
+       struct platform_device *ofdev;
 
-       ofdev = to_of_device(dev);
+       ofdev = to_platform_device(dev);
        of_node_put(ofdev->dev.of_node);
        kfree(ofdev);
 }
 EXPORT_SYMBOL(of_release_dev);
 
-int of_device_register(struct of_device *ofdev)
+int of_device_register(struct platform_device *ofdev)
 {
        BUG_ON(ofdev->dev.of_node == NULL);
 
        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 */
@@ -117,25 +119,24 @@ int of_device_register(struct of_device *ofdev)
 }
 EXPORT_SYMBOL(of_device_register);
 
-void of_device_unregister(struct of_device *ofdev)
+void of_device_unregister(struct platform_device *ofdev)
 {
        device_unregister(&ofdev->dev);
 }
 EXPORT_SYMBOL(of_device_unregister);
 
-ssize_t of_device_get_modalias(struct of_device *ofdev,
-                               char *str, ssize_t len)
+ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
 {
        const char *compat;
        int cplen, i;
        ssize_t tsize, csize, repend;
 
        /* Name & Type */
-       csize = snprintf(str, len, "of:N%sT%s", ofdev->dev.of_node->name,
-                        ofdev->dev.of_node->type);
+       csize = snprintf(str, len, "of:N%sT%s", dev->of_node->name,
+                        dev->of_node->type);
 
        /* Get compatible property if any */
-       compat = of_get_property(ofdev->dev.of_node, "compatible", &cplen);
+       compat = of_get_property(dev->of_node, "compatible", &cplen);
        if (!compat)
                return csize;
 
@@ -170,3 +171,51 @@ ssize_t of_device_get_modalias(struct of_device *ofdev,
 
        return tsize;
 }
+
+/**
+ * of_device_uevent - Display OF related uevent information
+ */
+int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       const char *compat;
+       int seen = 0, cplen, sl;
+
+       if ((!dev) || (!dev->of_node))
+               return -ENODEV;
+
+       if (add_uevent_var(env, "OF_NAME=%s", dev->of_node->name))
+               return -ENOMEM;
+
+       if (add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type))
+               return -ENOMEM;
+
+       /* Since the compatible field can contain pretty much anything
+        * it's not really legal to split it out with commas. We split it
+        * up using a number of environment variables instead. */
+
+       compat = of_get_property(dev->of_node, "compatible", &cplen);
+       while (compat && *compat && cplen > 0) {
+               if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
+                       return -ENOMEM;
+
+               sl = strlen(compat) + 1;
+               compat += sl;
+               cplen -= sl;
+               seen++;
+       }
+
+       if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
+               return -ENOMEM;
+
+       /* modalias is trickier, we add it in 2 steps */
+       if (add_uevent_var(env, "MODALIAS="))
+               return -ENOMEM;
+
+       sl = of_device_get_modalias(dev, &env->buf[env->buflen-1],
+                                   sizeof(env->buf) - env->buflen);
+       if (sl >= (sizeof(env->buf) - env->buflen))
+               return -ENOMEM;
+       env->buflen += sl;
+
+       return 0;
+}