of: Always use 'struct device.of_node' to get device node pointer.
[safe/jmp/linux-2.6] / drivers / of / device.c
index 7f233d7..24068bb 100644 (file)
@@ -1,42 +1,13 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
 
 #include <asm/errno.h>
-#include <asm/of_device.h>
-
-/**
- * of_match_node - Tell if an device_node has a matching of_match structure
- * @ids: array of of device match structures to search in
- * @node: the of device structure to match against
- *
- * Low level utility function used by device matching.
- */
-const struct of_device_id *of_match_node(const struct of_device_id *matches,
-                                        const struct device_node *node)
-{
-       while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
-               int match = 1;
-               if (matches->name[0])
-                       match &= node->name
-                               && !strcmp(matches->name, node->name);
-               if (matches->type[0])
-                       match &= node->type
-                               && !strcmp(matches->type, node->type);
-               if (matches->compatible[0])
-                       match &= of_device_is_compatible(node,
-                                               matches->compatible);
-               if (match)
-                       return matches;
-               matches++;
-       }
-       return NULL;
-}
-EXPORT_SYMBOL(of_match_node);
 
 /**
  * of_match_device - Tell if an of_device structure has a matching
@@ -50,9 +21,9 @@ EXPORT_SYMBOL(of_match_node);
 const struct of_device_id *of_match_device(const struct of_device_id *matches,
                                        const struct of_device *dev)
 {
-       if (!dev->node)
+       if (!dev->dev.of_node)
                return NULL;
-       return of_match_node(matches, dev->node);
+       return of_match_node(matches, dev->dev.of_node);
 }
 EXPORT_SYMBOL(of_match_device);
 
@@ -77,16 +48,42 @@ void of_dev_put(struct of_device *dev)
 }
 EXPORT_SYMBOL(of_dev_put);
 
-static ssize_t dev_show_devspec(struct device *dev,
+static ssize_t devspec_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct of_device *ofdev;
+
+       ofdev = to_of_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;
 
        ofdev = to_of_device(dev);
-       return sprintf(buf, "%s", ofdev->node->full_name);
+       return sprintf(buf, "%s\n", ofdev->dev.of_node->name);
 }
 
-static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+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);
+       buf[len] = '\n';
+       buf[len+1] = 0;
+       return len+1;
+}
+
+struct device_attribute of_platform_device_attrs[] = {
+       __ATTR_RO(devspec),
+       __ATTR_RO(name),
+       __ATTR_RO(modalias),
+       __ATTR_NULL
+};
 
 /**
  * of_release_dev - free an of device structure when all users of it are finished.
@@ -100,32 +97,77 @@ void of_release_dev(struct device *dev)
        struct of_device *ofdev;
 
        ofdev = to_of_device(dev);
-       of_node_put(ofdev->node);
+       of_node_put(ofdev->dev.of_node);
        kfree(ofdev);
 }
 EXPORT_SYMBOL(of_release_dev);
 
 int of_device_register(struct of_device *ofdev)
 {
-       int rc;
-
-       BUG_ON(ofdev->node == NULL);
+       BUG_ON(ofdev->dev.of_node == NULL);
 
-       rc = device_register(&ofdev->dev);
-       if (rc)
-               return rc;
+       device_initialize(&ofdev->dev);
 
-       rc = device_create_file(&ofdev->dev, &dev_attr_devspec);
-       if (rc)
-               device_unregister(&ofdev->dev);
+       /* 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 */
+       if (!ofdev->dev.parent)
+               set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node));
 
-       return rc;
+       return device_add(&ofdev->dev);
 }
 EXPORT_SYMBOL(of_device_register);
 
 void of_device_unregister(struct of_device *ofdev)
 {
-       device_remove_file(&ofdev->dev, &dev_attr_devspec);
        device_unregister(&ofdev->dev);
 }
 EXPORT_SYMBOL(of_device_unregister);
+
+ssize_t of_device_get_modalias(struct of_device *ofdev,
+                               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);
+
+       /* Get compatible property if any */
+       compat = of_get_property(ofdev->dev.of_node, "compatible", &cplen);
+       if (!compat)
+               return csize;
+
+       /* Find true end (we tolerate multiple \0 at the end */
+       for (i = (cplen - 1); i >= 0 && !compat[i]; i--)
+               cplen--;
+       if (!cplen)
+               return csize;
+       cplen++;
+
+       /* Check space (need cplen+1 chars including final \0) */
+       tsize = csize + cplen;
+       repend = tsize;
+
+       if (csize >= len)               /* @ the limit, all is already filled */
+               return tsize;
+
+       if (tsize >= len) {             /* limit compat list */
+               cplen = len - csize - 1;
+               repend = len;
+       }
+
+       /* Copy and do char replacement */
+       memcpy(&str[csize + 1], compat, cplen);
+       for (i = csize; i < repend; i++) {
+               char c = str[i];
+               if (c == '\0')
+                       str[i] = 'C';
+               else if (c == ' ')
+                       str[i] = '_';
+       }
+
+       return tsize;
+}