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        return device_register(&ofdev->dev);
 109}
 110EXPORT_SYMBOL(of_device_register);
 111
 112void of_device_unregister(struct of_device *ofdev)
 113{
 114        device_unregister(&ofdev->dev);
 115}
 116EXPORT_SYMBOL(of_device_unregister);
 117
 118ssize_t of_device_get_modalias(struct of_device *ofdev,
 119                                char *str, ssize_t len)
 120{
 121        const char *compat;
 122        int cplen, i;
 123        ssize_t tsize, csize, repend;
 124
 125        /* Name & Type */
 126        csize = snprintf(str, len, "of:N%sT%s",
 127                                ofdev->node->name, ofdev->node->type);
 128
 129        /* Get compatible property if any */
 130        compat = of_get_property(ofdev->node, "compatible", &cplen);
 131        if (!compat)
 132                return csize;
 133
 134        /* Find true end (we tolerate multiple \0 at the end */
 135        for (i = (cplen - 1); i >= 0 && !compat[i]; i--)
 136                cplen--;
 137        if (!cplen)
 138                return csize;
 139        cplen++;
 140
 141        /* Check space (need cplen+1 chars including final \0) */
 142        tsize = csize + cplen;
 143        repend = tsize;
 144
 145        if (csize >= len)               /* @ the limit, all is already filled */
 146                return tsize;
 147
 148        if (tsize >= len) {             /* limit compat list */
 149                cplen = len - csize - 1;
 150                repend = len;
 151        }
 152
 153        /* Copy and do char replacement */
 154        memcpy(&str[csize + 1], compat, cplen);
 155        for (i = csize; i < repend; i++) {
 156                char c = str[i];
 157                if (c == '\0')
 158                        str[i] = 'C';
 159                else if (c == ' ')
 160                        str[i] = '_';
 161        }
 162
 163        return tsize;
 164}
 165