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