uboot/drivers/core/device.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Device manager
   4 *
   5 * Copyright (c) 2013 Google, Inc
   6 *
   7 * (C) Copyright 2012
   8 * Pavel Herrmann <morpheus.ibis@gmail.com>
   9 */
  10
  11#include <common.h>
  12#include <asm/io.h>
  13#include <clk.h>
  14#include <fdtdec.h>
  15#include <fdt_support.h>
  16#include <malloc.h>
  17#include <dm/device.h>
  18#include <dm/device-internal.h>
  19#include <dm/lists.h>
  20#include <dm/of_access.h>
  21#include <dm/pinctrl.h>
  22#include <dm/platdata.h>
  23#include <dm/read.h>
  24#include <dm/uclass.h>
  25#include <dm/uclass-internal.h>
  26#include <dm/util.h>
  27#include <linux/err.h>
  28#include <linux/list.h>
  29#include <power-domain.h>
  30
  31DECLARE_GLOBAL_DATA_PTR;
  32
  33static int device_bind_common(struct udevice *parent, const struct driver *drv,
  34                              const char *name, void *platdata,
  35                              ulong driver_data, ofnode node,
  36                              uint of_platdata_size, struct udevice **devp)
  37{
  38        struct udevice *dev;
  39        struct uclass *uc;
  40        int size, ret = 0;
  41
  42        if (devp)
  43                *devp = NULL;
  44        if (!name)
  45                return -EINVAL;
  46
  47        ret = uclass_get(drv->id, &uc);
  48        if (ret) {
  49                debug("Missing uclass for driver %s\n", drv->name);
  50                return ret;
  51        }
  52
  53        dev = calloc(1, sizeof(struct udevice));
  54        if (!dev)
  55                return -ENOMEM;
  56
  57        INIT_LIST_HEAD(&dev->sibling_node);
  58        INIT_LIST_HEAD(&dev->child_head);
  59        INIT_LIST_HEAD(&dev->uclass_node);
  60#ifdef CONFIG_DEVRES
  61        INIT_LIST_HEAD(&dev->devres_head);
  62#endif
  63        dev->platdata = platdata;
  64        dev->driver_data = driver_data;
  65        dev->name = name;
  66        dev->node = node;
  67        dev->parent = parent;
  68        dev->driver = drv;
  69        dev->uclass = uc;
  70
  71        dev->seq = -1;
  72        dev->req_seq = -1;
  73        if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS)) {
  74                /*
  75                 * Some devices, such as a SPI bus, I2C bus and serial ports
  76                 * are numbered using aliases.
  77                 *
  78                 * This is just a 'requested' sequence, and will be
  79                 * resolved (and ->seq updated) when the device is probed.
  80                 */
  81                if (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS) {
  82                        if (uc->uc_drv->name && ofnode_valid(node)) {
  83                                dev_read_alias_seq(dev, &dev->req_seq);
  84                        }
  85                }
  86        }
  87
  88        if (drv->platdata_auto_alloc_size) {
  89                bool alloc = !platdata;
  90
  91                if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
  92                        if (of_platdata_size) {
  93                                dev->flags |= DM_FLAG_OF_PLATDATA;
  94                                if (of_platdata_size <
  95                                                drv->platdata_auto_alloc_size)
  96                                        alloc = true;
  97                        }
  98                }
  99                if (alloc) {
 100                        dev->flags |= DM_FLAG_ALLOC_PDATA;
 101                        dev->platdata = calloc(1,
 102                                               drv->platdata_auto_alloc_size);
 103                        if (!dev->platdata) {
 104                                ret = -ENOMEM;
 105                                goto fail_alloc1;
 106                        }
 107                        if (CONFIG_IS_ENABLED(OF_PLATDATA) && platdata) {
 108                                memcpy(dev->platdata, platdata,
 109                                       of_platdata_size);
 110                        }
 111                }
 112        }
 113
 114        size = uc->uc_drv->per_device_platdata_auto_alloc_size;
 115        if (size) {
 116                dev->flags |= DM_FLAG_ALLOC_UCLASS_PDATA;
 117                dev->uclass_platdata = calloc(1, size);
 118                if (!dev->uclass_platdata) {
 119                        ret = -ENOMEM;
 120                        goto fail_alloc2;
 121                }
 122        }
 123
 124        if (parent) {
 125                size = parent->driver->per_child_platdata_auto_alloc_size;
 126                if (!size) {
 127                        size = parent->uclass->uc_drv->
 128                                        per_child_platdata_auto_alloc_size;
 129                }
 130                if (size) {
 131                        dev->flags |= DM_FLAG_ALLOC_PARENT_PDATA;
 132                        dev->parent_platdata = calloc(1, size);
 133                        if (!dev->parent_platdata) {
 134                                ret = -ENOMEM;
 135                                goto fail_alloc3;
 136                        }
 137                }
 138        }
 139
 140        /* put dev into parent's successor list */
 141        if (parent)
 142                list_add_tail(&dev->sibling_node, &parent->child_head);
 143
 144        ret = uclass_bind_device(dev);
 145        if (ret)
 146                goto fail_uclass_bind;
 147
 148        /* if we fail to bind we remove device from successors and free it */
 149        if (drv->bind) {
 150                ret = drv->bind(dev);
 151                if (ret)
 152                        goto fail_bind;
 153        }
 154        if (parent && parent->driver->child_post_bind) {
 155                ret = parent->driver->child_post_bind(dev);
 156                if (ret)
 157                        goto fail_child_post_bind;
 158        }
 159        if (uc->uc_drv->post_bind) {
 160                ret = uc->uc_drv->post_bind(dev);
 161                if (ret)
 162                        goto fail_uclass_post_bind;
 163        }
 164
 165        if (parent)
 166                pr_debug("Bound device %s to %s\n", dev->name, parent->name);
 167        if (devp)
 168                *devp = dev;
 169
 170        dev->flags |= DM_FLAG_BOUND;
 171
 172        return 0;
 173
 174fail_uclass_post_bind:
 175        /* There is no child unbind() method, so no clean-up required */
 176fail_child_post_bind:
 177        if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
 178                if (drv->unbind && drv->unbind(dev)) {
 179                        dm_warn("unbind() method failed on dev '%s' on error path\n",
 180                                dev->name);
 181                }
 182        }
 183
 184fail_bind:
 185        if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
 186                if (uclass_unbind_device(dev)) {
 187                        dm_warn("Failed to unbind dev '%s' on error path\n",
 188                                dev->name);
 189                }
 190        }
 191fail_uclass_bind:
 192        if (CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)) {
 193                list_del(&dev->sibling_node);
 194                if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
 195                        free(dev->parent_platdata);
 196                        dev->parent_platdata = NULL;
 197                }
 198        }
 199fail_alloc3:
 200        if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
 201                free(dev->uclass_platdata);
 202                dev->uclass_platdata = NULL;
 203        }
 204fail_alloc2:
 205        if (dev->flags & DM_FLAG_ALLOC_PDATA) {
 206                free(dev->platdata);
 207                dev->platdata = NULL;
 208        }
 209fail_alloc1:
 210        devres_release_all(dev);
 211
 212        free(dev);
 213
 214        return ret;
 215}
 216
 217int device_bind_with_driver_data(struct udevice *parent,
 218                                 const struct driver *drv, const char *name,
 219                                 ulong driver_data, ofnode node,
 220                                 struct udevice **devp)
 221{
 222        return device_bind_common(parent, drv, name, NULL, driver_data, node,
 223                                  0, devp);
 224}
 225
 226int device_bind(struct udevice *parent, const struct driver *drv,
 227                const char *name, void *platdata, int of_offset,
 228                struct udevice **devp)
 229{
 230        return device_bind_common(parent, drv, name, platdata, 0,
 231                                  offset_to_ofnode(of_offset), 0, devp);
 232}
 233
 234int device_bind_ofnode(struct udevice *parent, const struct driver *drv,
 235                       const char *name, void *platdata, ofnode node,
 236                       struct udevice **devp)
 237{
 238        return device_bind_common(parent, drv, name, platdata, 0, node, 0,
 239                                  devp);
 240}
 241
 242int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
 243                        const struct driver_info *info, struct udevice **devp)
 244{
 245        struct driver *drv;
 246        uint platdata_size = 0;
 247
 248        drv = lists_driver_lookup_name(info->name);
 249        if (!drv)
 250                return -ENOENT;
 251        if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC))
 252                return -EPERM;
 253
 254#if CONFIG_IS_ENABLED(OF_PLATDATA)
 255        platdata_size = info->platdata_size;
 256#endif
 257        return device_bind_common(parent, drv, info->name,
 258                        (void *)info->platdata, 0, ofnode_null(), platdata_size,
 259                        devp);
 260}
 261
 262static void *alloc_priv(int size, uint flags)
 263{
 264        void *priv;
 265
 266        if (flags & DM_FLAG_ALLOC_PRIV_DMA) {
 267                size = ROUND(size, ARCH_DMA_MINALIGN);
 268                priv = memalign(ARCH_DMA_MINALIGN, size);
 269                if (priv) {
 270                        memset(priv, '\0', size);
 271
 272                        /*
 273                         * Ensure that the zero bytes are flushed to memory.
 274                         * This prevents problems if the driver uses this as
 275                         * both an input and an output buffer:
 276                         *
 277                         * 1. Zeroes written to buffer (here) and sit in the
 278                         *      cache
 279                         * 2. Driver issues a read command to DMA
 280                         * 3. CPU runs out of cache space and evicts some cache
 281                         *      data in the buffer, writing zeroes to RAM from
 282                         *      the memset() above
 283                         * 4. DMA completes
 284                         * 5. Buffer now has some DMA data and some zeroes
 285                         * 6. Data being read is now incorrect
 286                         *
 287                         * To prevent this, ensure that the cache is clean
 288                         * within this range at the start. The driver can then
 289                         * use normal flush-after-write, invalidate-before-read
 290                         * procedures.
 291                         *
 292                         * TODO(sjg@chromium.org): Drop this microblaze
 293                         * exception.
 294                         */
 295#ifndef CONFIG_MICROBLAZE
 296                        flush_dcache_range((ulong)priv, (ulong)priv + size);
 297#endif
 298                }
 299        } else {
 300                priv = calloc(1, size);
 301        }
 302
 303        return priv;
 304}
 305
 306int device_probe(struct udevice *dev)
 307{
 308        struct power_domain pd;
 309        const struct driver *drv;
 310        int size = 0;
 311        int ret;
 312        int seq;
 313
 314        if (!dev)
 315                return -EINVAL;
 316
 317        if (dev->flags & DM_FLAG_ACTIVATED)
 318                return 0;
 319
 320        drv = dev->driver;
 321        assert(drv);
 322
 323        /* Allocate private data if requested and not reentered */
 324        if (drv->priv_auto_alloc_size && !dev->priv) {
 325                dev->priv = alloc_priv(drv->priv_auto_alloc_size, drv->flags);
 326                if (!dev->priv) {
 327                        ret = -ENOMEM;
 328                        goto fail;
 329                }
 330        }
 331        /* Allocate private data if requested and not reentered */
 332        size = dev->uclass->uc_drv->per_device_auto_alloc_size;
 333        if (size && !dev->uclass_priv) {
 334                dev->uclass_priv = alloc_priv(size,
 335                                              dev->uclass->uc_drv->flags);
 336                if (!dev->uclass_priv) {
 337                        ret = -ENOMEM;
 338                        goto fail;
 339                }
 340        }
 341
 342        /* Ensure all parents are probed */
 343        if (dev->parent) {
 344                size = dev->parent->driver->per_child_auto_alloc_size;
 345                if (!size) {
 346                        size = dev->parent->uclass->uc_drv->
 347                                        per_child_auto_alloc_size;
 348                }
 349                if (size && !dev->parent_priv) {
 350                        dev->parent_priv = alloc_priv(size, drv->flags);
 351                        if (!dev->parent_priv) {
 352                                ret = -ENOMEM;
 353                                goto fail;
 354                        }
 355                }
 356
 357                ret = device_probe(dev->parent);
 358                if (ret)
 359                        goto fail;
 360
 361                /*
 362                 * The device might have already been probed during
 363                 * the call to device_probe() on its parent device
 364                 * (e.g. PCI bridge devices). Test the flags again
 365                 * so that we don't mess up the device.
 366                 */
 367                if (dev->flags & DM_FLAG_ACTIVATED)
 368                        return 0;
 369        }
 370
 371        seq = uclass_resolve_seq(dev);
 372        if (seq < 0) {
 373                ret = seq;
 374                goto fail;
 375        }
 376        dev->seq = seq;
 377
 378        dev->flags |= DM_FLAG_ACTIVATED;
 379
 380        /*
 381         * Process pinctrl for everything except the root device, and
 382         * continue regardless of the result of pinctrl. Don't process pinctrl
 383         * settings for pinctrl devices since the device may not yet be
 384         * probed.
 385         */
 386        if (dev->parent && device_get_uclass_id(dev) != UCLASS_PINCTRL)
 387                pinctrl_select_state(dev, "default");
 388
 389        if (dev->parent && device_get_uclass_id(dev) != UCLASS_POWER_DOMAIN) {
 390                if (!power_domain_get(dev, &pd))
 391                        power_domain_on(&pd);
 392        }
 393
 394        ret = uclass_pre_probe_device(dev);
 395        if (ret)
 396                goto fail;
 397
 398        if (dev->parent && dev->parent->driver->child_pre_probe) {
 399                ret = dev->parent->driver->child_pre_probe(dev);
 400                if (ret)
 401                        goto fail;
 402        }
 403
 404        if (drv->ofdata_to_platdata && dev_has_of_node(dev)) {
 405                ret = drv->ofdata_to_platdata(dev);
 406                if (ret)
 407                        goto fail;
 408        }
 409
 410        /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
 411        ret = clk_set_defaults(dev);
 412        if (ret)
 413                goto fail;
 414
 415        if (drv->probe) {
 416                ret = drv->probe(dev);
 417                if (ret) {
 418                        dev->flags &= ~DM_FLAG_ACTIVATED;
 419                        goto fail;
 420                }
 421        }
 422
 423        ret = uclass_post_probe_device(dev);
 424        if (ret)
 425                goto fail_uclass;
 426
 427        if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL)
 428                pinctrl_select_state(dev, "default");
 429
 430        return 0;
 431fail_uclass:
 432        if (device_remove(dev, DM_REMOVE_NORMAL)) {
 433                dm_warn("%s: Device '%s' failed to remove on error path\n",
 434                        __func__, dev->name);
 435        }
 436fail:
 437        dev->flags &= ~DM_FLAG_ACTIVATED;
 438
 439        dev->seq = -1;
 440        device_free(dev);
 441
 442        return ret;
 443}
 444
 445void *dev_get_platdata(const struct udevice *dev)
 446{
 447        if (!dev) {
 448                dm_warn("%s: null device\n", __func__);
 449                return NULL;
 450        }
 451
 452        return dev->platdata;
 453}
 454
 455void *dev_get_parent_platdata(const struct udevice *dev)
 456{
 457        if (!dev) {
 458                dm_warn("%s: null device\n", __func__);
 459                return NULL;
 460        }
 461
 462        return dev->parent_platdata;
 463}
 464
 465void *dev_get_uclass_platdata(const struct udevice *dev)
 466{
 467        if (!dev) {
 468                dm_warn("%s: null device\n", __func__);
 469                return NULL;
 470        }
 471
 472        return dev->uclass_platdata;
 473}
 474
 475void *dev_get_priv(const struct udevice *dev)
 476{
 477        if (!dev) {
 478                dm_warn("%s: null device\n", __func__);
 479                return NULL;
 480        }
 481
 482        return dev->priv;
 483}
 484
 485void *dev_get_uclass_priv(const struct udevice *dev)
 486{
 487        if (!dev) {
 488                dm_warn("%s: null device\n", __func__);
 489                return NULL;
 490        }
 491
 492        return dev->uclass_priv;
 493}
 494
 495void *dev_get_parent_priv(const struct udevice *dev)
 496{
 497        if (!dev) {
 498                dm_warn("%s: null device\n", __func__);
 499                return NULL;
 500        }
 501
 502        return dev->parent_priv;
 503}
 504
 505static int device_get_device_tail(struct udevice *dev, int ret,
 506                                  struct udevice **devp)
 507{
 508        if (ret)
 509                return ret;
 510
 511        ret = device_probe(dev);
 512        if (ret)
 513                return ret;
 514
 515        *devp = dev;
 516
 517        return 0;
 518}
 519
 520/**
 521 * device_find_by_ofnode() - Return device associated with given ofnode
 522 *
 523 * The returned device is *not* activated.
 524 *
 525 * @node: The ofnode for which a associated device should be looked up
 526 * @devp: Pointer to structure to hold the found device
 527 * Return: 0 if OK, -ve on error
 528 */
 529static int device_find_by_ofnode(ofnode node, struct udevice **devp)
 530{
 531        struct uclass *uc;
 532        struct udevice *dev;
 533        int ret;
 534
 535        list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
 536                ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node,
 537                                                   &dev);
 538                if (!ret || dev) {
 539                        *devp = dev;
 540                        return 0;
 541                }
 542        }
 543
 544        return -ENODEV;
 545}
 546
 547int device_get_child(struct udevice *parent, int index, struct udevice **devp)
 548{
 549        struct udevice *dev;
 550
 551        list_for_each_entry(dev, &parent->child_head, sibling_node) {
 552                if (!index--)
 553                        return device_get_device_tail(dev, 0, devp);
 554        }
 555
 556        return -ENODEV;
 557}
 558
 559int device_find_child_by_seq(struct udevice *parent, int seq_or_req_seq,
 560                             bool find_req_seq, struct udevice **devp)
 561{
 562        struct udevice *dev;
 563
 564        *devp = NULL;
 565        if (seq_or_req_seq == -1)
 566                return -ENODEV;
 567
 568        list_for_each_entry(dev, &parent->child_head, sibling_node) {
 569                if ((find_req_seq ? dev->req_seq : dev->seq) ==
 570                                seq_or_req_seq) {
 571                        *devp = dev;
 572                        return 0;
 573                }
 574        }
 575
 576        return -ENODEV;
 577}
 578
 579int device_get_child_by_seq(struct udevice *parent, int seq,
 580                            struct udevice **devp)
 581{
 582        struct udevice *dev;
 583        int ret;
 584
 585        *devp = NULL;
 586        ret = device_find_child_by_seq(parent, seq, false, &dev);
 587        if (ret == -ENODEV) {
 588                /*
 589                 * We didn't find it in probed devices. See if there is one
 590                 * that will request this seq if probed.
 591                 */
 592                ret = device_find_child_by_seq(parent, seq, true, &dev);
 593        }
 594        return device_get_device_tail(dev, ret, devp);
 595}
 596
 597int device_find_child_by_of_offset(struct udevice *parent, int of_offset,
 598                                   struct udevice **devp)
 599{
 600        struct udevice *dev;
 601
 602        *devp = NULL;
 603
 604        list_for_each_entry(dev, &parent->child_head, sibling_node) {
 605                if (dev_of_offset(dev) == of_offset) {
 606                        *devp = dev;
 607                        return 0;
 608                }
 609        }
 610
 611        return -ENODEV;
 612}
 613
 614int device_get_child_by_of_offset(struct udevice *parent, int node,
 615                                  struct udevice **devp)
 616{
 617        struct udevice *dev;
 618        int ret;
 619
 620        *devp = NULL;
 621        ret = device_find_child_by_of_offset(parent, node, &dev);
 622        return device_get_device_tail(dev, ret, devp);
 623}
 624
 625static struct udevice *_device_find_global_by_ofnode(struct udevice *parent,
 626                                                     ofnode ofnode)
 627{
 628        struct udevice *dev, *found;
 629
 630        if (ofnode_equal(dev_ofnode(parent), ofnode))
 631                return parent;
 632
 633        list_for_each_entry(dev, &parent->child_head, sibling_node) {
 634                found = _device_find_global_by_ofnode(dev, ofnode);
 635                if (found)
 636                        return found;
 637        }
 638
 639        return NULL;
 640}
 641
 642int device_find_global_by_ofnode(ofnode ofnode, struct udevice **devp)
 643{
 644        *devp = _device_find_global_by_ofnode(gd->dm_root, ofnode);
 645
 646        return *devp ? 0 : -ENOENT;
 647}
 648
 649int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp)
 650{
 651        struct udevice *dev;
 652
 653        dev = _device_find_global_by_ofnode(gd->dm_root, ofnode);
 654        return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
 655}
 656
 657int device_find_first_child(struct udevice *parent, struct udevice **devp)
 658{
 659        if (list_empty(&parent->child_head)) {
 660                *devp = NULL;
 661        } else {
 662                *devp = list_first_entry(&parent->child_head, struct udevice,
 663                                         sibling_node);
 664        }
 665
 666        return 0;
 667}
 668
 669int device_find_next_child(struct udevice **devp)
 670{
 671        struct udevice *dev = *devp;
 672        struct udevice *parent = dev->parent;
 673
 674        if (list_is_last(&dev->sibling_node, &parent->child_head)) {
 675                *devp = NULL;
 676        } else {
 677                *devp = list_entry(dev->sibling_node.next, struct udevice,
 678                                   sibling_node);
 679        }
 680
 681        return 0;
 682}
 683
 684int device_find_first_inactive_child(struct udevice *parent,
 685                                     enum uclass_id uclass_id,
 686                                     struct udevice **devp)
 687{
 688        struct udevice *dev;
 689
 690        *devp = NULL;
 691        list_for_each_entry(dev, &parent->child_head, sibling_node) {
 692                if (!device_active(dev) &&
 693                    device_get_uclass_id(dev) == uclass_id) {
 694                        *devp = dev;
 695                        return 0;
 696                }
 697        }
 698
 699        return -ENODEV;
 700}
 701
 702struct udevice *dev_get_parent(const struct udevice *child)
 703{
 704        return child->parent;
 705}
 706
 707ulong dev_get_driver_data(const struct udevice *dev)
 708{
 709        return dev->driver_data;
 710}
 711
 712const void *dev_get_driver_ops(const struct udevice *dev)
 713{
 714        if (!dev || !dev->driver->ops)
 715                return NULL;
 716
 717        return dev->driver->ops;
 718}
 719
 720enum uclass_id device_get_uclass_id(const struct udevice *dev)
 721{
 722        return dev->uclass->uc_drv->id;
 723}
 724
 725const char *dev_get_uclass_name(const struct udevice *dev)
 726{
 727        if (!dev)
 728                return NULL;
 729
 730        return dev->uclass->uc_drv->name;
 731}
 732
 733bool device_has_children(const struct udevice *dev)
 734{
 735        return !list_empty(&dev->child_head);
 736}
 737
 738bool device_has_active_children(struct udevice *dev)
 739{
 740        struct udevice *child;
 741
 742        for (device_find_first_child(dev, &child);
 743             child;
 744             device_find_next_child(&child)) {
 745                if (device_active(child))
 746                        return true;
 747        }
 748
 749        return false;
 750}
 751
 752bool device_is_last_sibling(struct udevice *dev)
 753{
 754        struct udevice *parent = dev->parent;
 755
 756        if (!parent)
 757                return false;
 758        return list_is_last(&dev->sibling_node, &parent->child_head);
 759}
 760
 761void device_set_name_alloced(struct udevice *dev)
 762{
 763        dev->flags |= DM_FLAG_NAME_ALLOCED;
 764}
 765
 766int device_set_name(struct udevice *dev, const char *name)
 767{
 768        name = strdup(name);
 769        if (!name)
 770                return -ENOMEM;
 771        dev->name = name;
 772        device_set_name_alloced(dev);
 773
 774        return 0;
 775}
 776
 777bool device_is_compatible(struct udevice *dev, const char *compat)
 778{
 779        return ofnode_device_is_compatible(dev_ofnode(dev), compat);
 780}
 781
 782bool of_machine_is_compatible(const char *compat)
 783{
 784        const void *fdt = gd->fdt_blob;
 785
 786        return !fdt_node_check_compatible(fdt, 0, compat);
 787}
 788
 789int dev_disable_by_path(const char *path)
 790{
 791        struct uclass *uc;
 792        ofnode node = ofnode_path(path);
 793        struct udevice *dev;
 794        int ret = 1;
 795
 796        if (!of_live_active())
 797                return -ENOSYS;
 798
 799        list_for_each_entry(uc, &gd->uclass_root, sibling_node) {
 800                ret = uclass_find_device_by_ofnode(uc->uc_drv->id, node, &dev);
 801                if (!ret)
 802                        break;
 803        }
 804
 805        if (ret)
 806                return ret;
 807
 808        ret = device_remove(dev, DM_REMOVE_NORMAL);
 809        if (ret)
 810                return ret;
 811
 812        ret = device_unbind(dev);
 813        if (ret)
 814                return ret;
 815
 816        return ofnode_set_enabled(node, false);
 817}
 818
 819int dev_enable_by_path(const char *path)
 820{
 821        ofnode node = ofnode_path(path);
 822        ofnode pnode = ofnode_get_parent(node);
 823        struct udevice *parent;
 824        int ret = 1;
 825
 826        if (!of_live_active())
 827                return -ENOSYS;
 828
 829        ret = device_find_by_ofnode(pnode, &parent);
 830        if (ret)
 831                return ret;
 832
 833        ret = ofnode_set_enabled(node, true);
 834        if (ret)
 835                return ret;
 836
 837        return lists_bind_fdt(parent, node, NULL);
 838}
 839