linux/drivers/of/device.c
<<
>>
Prefs
   1#include <linux/string.h>
   2#include <linux/kernel.h>
   3#include <linux/of.h>
   4#include <linux/of_device.h>
   5#include <linux/init.h>
   6#include <linux/module.h>
   7#include <linux/mod_devicetable.h>
   8#include <linux/slab.h>
   9
  10#include <asm/errno.h>
  11
  12/**
  13 * of_match_device - Tell if an of_device structure has a matching
  14 * of_match structure
  15 * @ids: array of of device match structures to search in
  16 * @dev: the of device structure to match against
  17 *
  18 * Used by a driver to check whether an of_device present in the
  19 * system is in its list of supported devices.
  20 */
  21const struct of_device_id *of_match_device(const struct of_device_id *matches,
  22                                        const struct of_device *dev)
  23{
  24        if (!dev->node)
  25                return NULL;
  26        return of_match_node(matches, dev->node);
  27}
  28EXPORT_SYMBOL(of_match_device);
  29
  30struct of_device *of_dev_get(struct of_device *dev)
  31{
  32        struct device *tmp;
  33
  34        if (!dev)
  35                return NULL;
  36        tmp = get_device(&dev->dev);
  37        if (tmp)
  38                return to_of_device(tmp);
  39        else
  40                return NULL;
  41}
  42EXPORT_SYMBOL(of_dev_get);
  43
  44void of_dev_put(struct of_device *dev)
  45{
  46        if (dev)
  47                put_device(&dev->dev);
  48}
  49EXPORT_SYMBOL(of_dev_put);
  50
  51static ssize_t devspec_show(struct device *dev,
  52                                struct device_attribute *attr, char *buf)
  53{
  54        struct of_device *ofdev;
  55
  56        ofdev = to_of_device(dev);
  57        return sprintf(buf, "%s\n", ofdev->node->full_name);
  58}
  59
  60static ssize_t name_show(struct device *dev,
  61                                struct device_attribute *attr, char *buf)
  62{
  63        struct of_device *ofdev;
  64
  65        ofdev = to_of_device(dev);
  66        return sprintf(buf, "%s\n", ofdev->node->name);
  67}
  68
  69static ssize_t modalias_show(struct device *dev,
  70                                struct device_attribute *attr, char *buf)
  71{
  72        struct of_device *ofdev = to_of_device(dev);
  73        ssize_t len = 0;
  74
  75        len = of_device_get_modalias(ofdev, buf, PAGE_SIZE - 2);
  76        buf[len] = '\n';
  77        buf[len+1] = 0;
  78        return len+1;
  79}
  80
  81struct device_attribute of_platform_device_attrs[] = {
  82        __ATTR_RO(devspec),
  83        __ATTR_RO(name),
  84        __ATTR_RO(modalias),
  85        __ATTR_NULL
  86};
  87
  88/**
  89 * of_release_dev - free an of device structure when all users of it are finished.
  90 * @dev: device that's been disconnected
  91 *
  92 * Will be called only by the device core when all users of this of device are
  93 * done.
  94 */
  95void of_release_dev(struct device *dev)
  96{
  97        struct of_device *ofdev;
  98
  99        ofdev = to_of_device(dev);
 100        of_node_put(ofdev->node);
 101        kfree(ofdev);
 102}
 103EXPORT_SYMBOL(of_release_dev);
 104
 105int of_device_register(struct of_device *ofdev)
 106{
 107        BUG_ON(ofdev->node == NULL);
 108
 109        device_initialize(&ofdev->dev);
 110
 111        /* device_add will assume that this device is on the same node as
 112         * the parent. If there is no parent defined, set the node
 113         * explicitly */
 114        if (!ofdev->dev.parent)
 115                set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->node));
 116
 117        return device_add(&ofdev->dev);
 118}
 119EXPORT_SYMBOL(of_device_register);
 120
 121void of_device_unregister(struct of_device *ofdev)
 122{
 123        device_unregister(&ofdev->dev);
 124}
 125EXPORT_SYMBOL(of_device_unregister);
 126
 127ssize_t of_device_get_modalias(struct of_device *ofdev,
 128                                char *str, ssize_t len)
 129{
 130        const char *compat;
 131        int cplen, i;
 132        ssize_t tsize, csize, repend;
 133
 134        /* Name & Type */
 135        csize = snprintf(str, len, "of:N%sT%s",
 136                                ofdev->node->name, ofdev->node->type);
 137
 138        /* Get compatible property if any */
 139        compat = of_get_property(ofdev->node, "compatible", &cplen);
 140        if (!compat)
 141                return csize;
 142
 143        /* Find true end (we tolerate multiple \0 at the end */
 144        for (i = (cplen - 1); i >= 0 && !compat[i]; i--)
 145                cplen--;
 146        if (!cplen)
 147                return csize;
 148        cplen++;
 149
 150        /* Check space (need cplen+1 chars including final \0) */
 151        tsize = csize + cplen;
 152        repend = tsize;
 153
 154        if (csize >= len)               /* @ the limit, all is already filled */
 155                return tsize;
 156
 157        if (tsize >= len) {             /* limit compat list */
 158                cplen = len - csize - 1;
 159                repend = len;
 160        }
 161
 162        /* Copy and do char replacement */
 163        memcpy(&str[csize + 1], compat, cplen);
 164        for (i = csize; i < repend; i++) {
 165                char c = str[i];
 166                if (c == '\0')
 167                        str[i] = 'C';
 168                else if (c == ' ')
 169                        str[i] = '_';
 170        }
 171
 172        return tsize;
 173}
 174