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 *
  80 * Try to get devices's DMA configuration from DT and update it
  81 * accordingly.
  82 *
  83 * If platform code needs to use its own special DMA configuration, it
  84 * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  85 * to fix up DMA configuration.
  86 */
  87int of_dma_configure(struct device *dev, struct device_node *np)
  88{
  89        u64 dma_addr, paddr, size = 0;
  90        int ret;
  91        bool coherent;
  92        unsigned long offset;
  93        const struct iommu_ops *iommu;
  94        u64 mask;
  95
  96        ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
  97        if (ret < 0) {
  98                /*
  99                 * For legacy reasons, we have to assume some devices need
 100                 * DMA configuration regardless of whether "dma-ranges" is
 101                 * correctly specified or not.
 102                 */
 103                if (!dev->bus->force_dma)
 104                        return ret == -ENODEV ? 0 : ret;
 105
 106                dma_addr = offset = 0;
 107        } else {
 108                offset = PFN_DOWN(paddr - dma_addr);
 109
 110                /*
 111                 * Add a work around to treat the size as mask + 1 in case
 112                 * it is defined in DT as a mask.
 113                 */
 114                if (size & 1) {
 115                        dev_warn(dev, "Invalid size 0x%llx for dma-range\n",
 116                                 size);
 117                        size = size + 1;
 118                }
 119
 120                if (!size) {
 121                        dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
 122                        return -EINVAL;
 123                }
 124                dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
 125        }
 126
 127        /*
 128         * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
 129         * setup the correct supported mask.
 130         */
 131        if (!dev->coherent_dma_mask)
 132                dev->coherent_dma_mask = DMA_BIT_MASK(32);
 133        /*
 134         * Set it to coherent_dma_mask by default if the architecture
 135         * code has not set it.
 136         */
 137        if (!dev->dma_mask)
 138                dev->dma_mask = &dev->coherent_dma_mask;
 139
 140        if (!size)
 141                size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
 142
 143        dev->dma_pfn_offset = offset;
 144
 145        /*
 146         * Limit coherent and dma mask based on size and default mask
 147         * set by the driver.
 148         */
 149        mask = DMA_BIT_MASK(ilog2(dma_addr + size - 1) + 1);
 150        dev->coherent_dma_mask &= mask;
 151        *dev->dma_mask &= mask;
 152
 153        coherent = of_dma_is_coherent(np);
 154        dev_dbg(dev, "device is%sdma coherent\n",
 155                coherent ? " " : " not ");
 156
 157        iommu = of_iommu_configure(dev, np);
 158        if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
 159                return -EPROBE_DEFER;
 160
 161        dev_dbg(dev, "device is%sbehind an iommu\n",
 162                iommu ? " " : " not ");
 163
 164        arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
 165
 166        return 0;
 167}
 168EXPORT_SYMBOL_GPL(of_dma_configure);
 169
 170/**
 171 * of_dma_deconfigure - Clean up DMA configuration
 172 * @dev:        Device for which to clean up DMA configuration
 173 *
 174 * Clean up all configuration performed by of_dma_configure_ops() and free all
 175 * resources that have been allocated.
 176 */
 177void of_dma_deconfigure(struct device *dev)
 178{
 179        arch_teardown_dma_ops(dev);
 180}
 181
 182int of_device_register(struct platform_device *pdev)
 183{
 184        device_initialize(&pdev->dev);
 185        return of_device_add(pdev);
 186}
 187EXPORT_SYMBOL(of_device_register);
 188
 189void of_device_unregister(struct platform_device *ofdev)
 190{
 191        device_unregister(&ofdev->dev);
 192}
 193EXPORT_SYMBOL(of_device_unregister);
 194
 195const void *of_device_get_match_data(const struct device *dev)
 196{
 197        const struct of_device_id *match;
 198
 199        match = of_match_device(dev->driver->of_match_table, dev);
 200        if (!match)
 201                return NULL;
 202
 203        return match->data;
 204}
 205EXPORT_SYMBOL(of_device_get_match_data);
 206
 207static ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
 208{
 209        const char *compat;
 210        char *c;
 211        struct property *p;
 212        ssize_t csize;
 213        ssize_t tsize;
 214
 215        if ((!dev) || (!dev->of_node))
 216                return -ENODEV;
 217
 218        /* Name & Type */
 219        csize = snprintf(str, len, "of:N%sT%s", dev->of_node->name,
 220                         dev->of_node->type);
 221        tsize = csize;
 222        len -= csize;
 223        if (str)
 224                str += csize;
 225
 226        of_property_for_each_string(dev->of_node, "compatible", p, compat) {
 227                csize = strlen(compat) + 1;
 228                tsize += csize;
 229                if (csize > len)
 230                        continue;
 231
 232                csize = snprintf(str, len, "C%s", compat);
 233                for (c = str; c; ) {
 234                        c = strchr(c, ' ');
 235                        if (c)
 236                                *c++ = '_';
 237                }
 238                len -= csize;
 239                str += csize;
 240        }
 241
 242        return tsize;
 243}
 244
 245int of_device_request_module(struct device *dev)
 246{
 247        char *str;
 248        ssize_t size;
 249        int ret;
 250
 251        size = of_device_get_modalias(dev, NULL, 0);
 252        if (size < 0)
 253                return size;
 254
 255        str = kmalloc(size + 1, GFP_KERNEL);
 256        if (!str)
 257                return -ENOMEM;
 258
 259        of_device_get_modalias(dev, str, size);
 260        str[size] = '\0';
 261        ret = request_module(str);
 262        kfree(str);
 263
 264        return ret;
 265}
 266EXPORT_SYMBOL_GPL(of_device_request_module);
 267
 268/**
 269 * of_device_modalias - Fill buffer with newline terminated modalias string
 270 */
 271ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
 272{
 273        ssize_t sl = of_device_get_modalias(dev, str, len - 2);
 274        if (sl < 0)
 275                return sl;
 276        if (sl > len - 2)
 277                return -ENOMEM;
 278
 279        str[sl++] = '\n';
 280        str[sl] = 0;
 281        return sl;
 282}
 283EXPORT_SYMBOL_GPL(of_device_modalias);
 284
 285/**
 286 * of_device_uevent - Display OF related uevent information
 287 */
 288void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 289{
 290        const char *compat;
 291        struct alias_prop *app;
 292        struct property *p;
 293        int seen = 0;
 294
 295        if ((!dev) || (!dev->of_node))
 296                return;
 297
 298        add_uevent_var(env, "OF_NAME=%s", dev->of_node->name);
 299        add_uevent_var(env, "OF_FULLNAME=%pOF", dev->of_node);
 300        if (dev->of_node->type && strcmp("<NULL>", dev->of_node->type) != 0)
 301                add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type);
 302
 303        /* Since the compatible field can contain pretty much anything
 304         * it's not really legal to split it out with commas. We split it
 305         * up using a number of environment variables instead. */
 306        of_property_for_each_string(dev->of_node, "compatible", p, compat) {
 307                add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
 308                seen++;
 309        }
 310        add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
 311
 312        seen = 0;
 313        mutex_lock(&of_mutex);
 314        list_for_each_entry(app, &aliases_lookup, link) {
 315                if (dev->of_node == app->np) {
 316                        add_uevent_var(env, "OF_ALIAS_%d=%s", seen,
 317                                       app->alias);
 318                        seen++;
 319                }
 320        }
 321        mutex_unlock(&of_mutex);
 322}
 323
 324int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
 325{
 326        int sl;
 327
 328        if ((!dev) || (!dev->of_node))
 329                return -ENODEV;
 330
 331        /* Devicetree modalias is tricky, we add it in 2 steps */
 332        if (add_uevent_var(env, "MODALIAS="))
 333                return -ENOMEM;
 334
 335        sl = of_device_get_modalias(dev, &env->buf[env->buflen-1],
 336                                    sizeof(env->buf) - env->buflen);
 337        if (sl >= (sizeof(env->buf) - env->buflen))
 338                return -ENOMEM;
 339        env->buflen += sl;
 340
 341        return 0;
 342}
 343EXPORT_SYMBOL_GPL(of_device_uevent_modalias);
 344