linux/drivers/of/device.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/string.h>
   3#include <linux/kernel.h>
   4#include <linux/of.h>
   5#include <linux/of_device.h>
   6#include <linux/of_address.h>
   7#include <linux/of_iommu.h>
   8#include <linux/dma-mapping.h>
   9#include <linux/init.h>
  10#include <linux/module.h>
  11#include <linux/mod_devicetable.h>
  12#include <linux/slab.h>
  13#include <linux/platform_device.h>
  14
  15#include <asm/errno.h>
  16#include "of_private.h"
  17
  18/**
  19 * of_match_device - Tell if a struct device matches an of_device_id list
  20 * @ids: array of of device match structures to search in
  21 * @dev: the of device structure to match against
  22 *
  23 * Used by a driver to check whether an platform_device present in the
  24 * system is in its list of supported devices.
  25 */
  26const struct of_device_id *of_match_device(const struct of_device_id *matches,
  27                                           const struct device *dev)
  28{
  29        if ((!matches) || (!dev->of_node))
  30                return NULL;
  31        return of_match_node(matches, dev->of_node);
  32}
  33EXPORT_SYMBOL(of_match_device);
  34
  35struct platform_device *of_dev_get(struct platform_device *dev)
  36{
  37        struct device *tmp;
  38
  39        if (!dev)
  40                return NULL;
  41        tmp = get_device(&dev->dev);
  42        if (tmp)
  43                return to_platform_device(tmp);
  44        else
  45                return NULL;
  46}
  47EXPORT_SYMBOL(of_dev_get);
  48
  49void of_dev_put(struct platform_device *dev)
  50{
  51        if (dev)
  52                put_device(&dev->dev);
  53}
  54EXPORT_SYMBOL(of_dev_put);
  55
  56int of_device_add(struct platform_device *ofdev)
  57{
  58        BUG_ON(ofdev->dev.of_node == NULL);
  59
  60        /* name and id have to be set so that the platform bus doesn't get
  61         * confused on matching */
  62        ofdev->name = dev_name(&ofdev->dev);
  63        ofdev->id = PLATFORM_DEVID_NONE;
  64
  65        /*
  66         * If this device has not binding numa node in devicetree, that is
  67         * of_node_to_nid returns NUMA_NO_NODE. device_add will assume that this
  68         * device is on the same node as the parent.
  69         */
  70        set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node));
  71
  72        return device_add(&ofdev->dev);
  73}
  74
  75/**
  76 * of_dma_configure - Setup DMA configuration
  77 * @dev:        Device to apply DMA configuration
  78 * @np:         Pointer to OF node having DMA configuration
  79 * @force_dma:  Whether device is to be set up by of_dma_configure() even if
  80 *              DMA capability is not explicitly described by firmware.
  81 *
  82 * Try to get devices's DMA configuration from DT and update it
  83 * accordingly.
  84 *
  85 * If platform code needs to use its own special DMA configuration, it
  86 * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  87 * to fix up DMA configuration.
  88 */
  89int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)
  90{
  91        u64 dma_addr, paddr, size = 0;
  92        int ret;
  93        bool coherent;
  94        unsigned long offset;
  95        const struct iommu_ops *iommu;
  96        u64 mask;
  97
  98        ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
  99        if (ret < 0) {
 100                /*
 101                 * For legacy reasons, we have to assume some devices need
 102                 * DMA configuration regardless of whether "dma-ranges" is
 103                 * correctly specified or not.
 104                 */
 105                if (!force_dma)
 106                        return ret == -ENODEV ? 0 : ret;
 107
 108                dma_addr = offset = 0;
 109        } else {
 110                offset = PFN_DOWN(paddr - dma_addr);
 111
 112                /*
 113                 * Add a work around to treat the size as mask + 1 in case
 114                 * it is defined in DT as a mask.
 115                 */
 116                if (size & 1) {
 117                        dev_warn(dev, "Invalid size 0x%llx for dma-range\n",
 118                                 size);
 119                        size = size + 1;
 120                }
 121
 122                if (!size) {
 123                        dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
 124                        return -EINVAL;
 125                }
 126                dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
 127        }
 128
 129        /*
 130         * If @dev is expected to be DMA-capable then the bus code that created
 131         * it should have initialised its dma_mask pointer by this point. For
 132         * now, we'll continue the legacy behaviour of coercing it to the
 133         * coherent mask if not, but we'll no longer do so quietly.
 134         */
 135        if (!dev->dma_mask) {
 136                dev_warn(dev, "DMA mask not set\n");
 137                dev->dma_mask = &dev->coherent_dma_mask;
 138        }
 139
 140        if (!size && dev->coherent_dma_mask)
 141                size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
 142        else if (!size)
 143                size = 1ULL << 32;
 144
 145        dev->dma_pfn_offset = offset;
 146
 147        /*
 148         * Limit coherent and dma mask based on size and default mask
 149         * set by the driver.
 150         */
 151        mask = DMA_BIT_MASK(ilog2(dma_addr + size - 1) + 1);
 152        dev->coherent_dma_mask &= mask;
 153        *dev->dma_mask &= mask;
 154        /* ...but only set bus mask if we found valid dma-ranges earlier */
 155        if (!ret)
 156                dev->bus_dma_mask = mask;
 157
 158        coherent = of_dma_is_coherent(np);
 159        dev_dbg(dev, "device is%sdma coherent\n",
 160                coherent ? " " : " not ");
 161
 162        iommu = of_iommu_configure(dev, np);
 163        if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
 164                return -EPROBE_DEFER;
 165
 166        dev_dbg(dev, "device is%sbehind an iommu\n",
 167                iommu ? " " : " not ");
 168
 169        arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
 170
 171        return 0;
 172}
 173EXPORT_SYMBOL_GPL(of_dma_configure);
 174
 175int of_device_register(struct platform_device *pdev)
 176{
 177        device_initialize(&pdev->dev);
 178        return of_device_add(pdev);
 179}
 180EXPORT_SYMBOL(of_device_register);
 181
 182void of_device_unregister(struct platform_device *ofdev)
 183{
 184        device_unregister(&ofdev->dev);
 185}
 186EXPORT_SYMBOL(of_device_unregister);
 187
 188const void *of_device_get_match_data(const struct device *dev)
 189{
 190        const struct of_device_id *match;
 191
 192        match = of_match_device(dev->driver->of_match_table, dev);
 193        if (!match)
 194                return NULL;
 195
 196        return match->data;
 197}
 198EXPORT_SYMBOL(of_device_get_match_data);
 199
 200static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
 201{
 202        const char *compat;
 203        char *c;
 204        struct property *p;
 205        ssize_t csize;
 206        ssize_t tsize;
 207
 208        if ((!dev) || (!dev->of_node))
 209                return -ENODEV;
 210
 211        /* Name & Type */
 212        /* %p eats all alphanum characters, so %c must be used here */
 213        csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T',
 214                         dev->of_node->type);
 215        tsize = csize;
 216        len -= csize;
 217        if (str)
 218                str += csize;
 219
 220        of_property_for_each_string(dev->of_node, "compatible", p, compat) {
 221                csize = strlen(compat) + 1;
 222                tsize += csize;
 223                if (csize > len)
 224                        continue;
 225
 226                csize = snprintf(str, len, "C%s", compat);
 227                for (c = str; c; ) {
 228                        c = strchr(c, ' ');
 229                        if (c)
 230                                *c++ = '_';
 231                }
 232                len -= csize;
 233                str += csize;
 234        }
 235
 236        return tsize;
 237}
 238
 239int of_device_request_module(struct device *dev)
 240{
 241        char *str;
 242        ssize_t size;
 243        int ret;
 244
 245        size = of_device_get_modalias(dev, NULL, 0);
 246        if (size < 0)
 247                return size;
 248
 249        str = kmalloc(size + 1, GFP_KERNEL);
 250        if (!str)
 251                return -ENOMEM;
 252
 253        of_device_get_modalias(dev, str, size);
 254        str[size] = '\0';
 255        ret = request_module(str);
 256        kfree(str);
 257
 258        return ret;
 259}
 260EXPORT_SYMBOL_GPL(of_device_request_module);
 261
 262/**
 263 * of_device_modalias - Fill buffer with newline terminated modalias string
 264 */
 265ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
 266{
 267        ssize_t sl = of_device_get_modalias(dev, str, len - 2);
 268        if (sl < 0)
 269                return sl;
 270        if (sl > len - 2)
 271                return -ENOMEM;
 272
 273        str[sl++] = '\n';
 274        str[sl] = 0;
 275        return sl;
 276}
 277EXPORT_SYMBOL_GPL(of_device_modalias);
 278
 279/**
 280 * of_device_uevent - Display OF related uevent information
 281 */
 282void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 283{
 284        const char *compat;
 285        struct alias_prop *app;
 286        struct property *p;
 287        int seen = 0;
 288
 289        if ((!dev) || (!dev->of_node))
 290                return;
 291
 292        add_uevent_var(env, "OF_NAME=%pOFn", dev->of_node);
 293        add_uevent_var(env, "OF_FULLNAME=%pOF", dev->of_node);
 294        if (dev->of_node->type && strcmp("<NULL>", dev->of_node->type) != 0)
 295                add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type);
 296
 297        /* Since the compatible field can contain pretty much anything
 298         * it's not really legal to split it out with commas. We split it
 299         * up using a number of environment variables instead. */
 300        of_property_for_each_string(dev->of_node, "compatible", p, compat) {
 301                add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
 302                seen++;
 303        }
 304        add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
 305
 306        seen = 0;
 307        mutex_lock(&of_mutex);
 308        list_for_each_entry(app, &aliases_lookup, link) {
 309                if (dev->of_node == app->np) {
 310                        add_uevent_var(env, "OF_ALIAS_%d=%s", seen,
 311                                       app->alias);
 312                        seen++;
 313                }
 314        }
 315        mutex_unlock(&of_mutex);
 316}
 317
 318int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
 319{
 320        int sl;
 321
 322        if ((!dev) || (!dev->of_node))
 323                return -ENODEV;
 324
 325        /* Devicetree modalias is tricky, we add it in 2 steps */
 326        if (add_uevent_var(env, "MODALIAS="))
 327                return -ENOMEM;
 328
 329        sl = of_device_get_modalias(dev, &env->buf[env->buflen-1],
 330                                    sizeof(env->buf) - env->buflen);
 331        if (sl >= (sizeof(env->buf) - env->buflen))
 332                return -ENOMEM;
 333        env->buflen += sl;
 334
 335        return 0;
 336}
 337EXPORT_SYMBOL_GPL(of_device_uevent_modalias);
 338