uboot/drivers/core/root.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2013 Google, Inc
   4 *
   5 * (C) Copyright 2012
   6 * Pavel Herrmann <morpheus.ibis@gmail.com>
   7 */
   8
   9#include <common.h>
  10#include <errno.h>
  11#include <fdtdec.h>
  12#include <log.h>
  13#include <malloc.h>
  14#include <asm/global_data.h>
  15#include <linux/libfdt.h>
  16#include <dm/acpi.h>
  17#include <dm/device.h>
  18#include <dm/device-internal.h>
  19#include <dm/lists.h>
  20#include <dm/of.h>
  21#include <dm/of_access.h>
  22#include <dm/platdata.h>
  23#include <dm/read.h>
  24#include <dm/root.h>
  25#include <dm/uclass.h>
  26#include <dm/util.h>
  27#include <linux/list.h>
  28
  29DECLARE_GLOBAL_DATA_PTR;
  30
  31static struct driver_info root_info = {
  32        .name           = "root_driver",
  33};
  34
  35struct udevice *dm_root(void)
  36{
  37        if (!gd->dm_root) {
  38                dm_warn("Virtual root driver does not exist!\n");
  39                return NULL;
  40        }
  41
  42        return gd->dm_root;
  43}
  44
  45void dm_fixup_for_gd_move(struct global_data *new_gd)
  46{
  47        /* The sentinel node has moved, so update things that point to it */
  48        if (gd->dm_root) {
  49                new_gd->uclass_root->next->prev = new_gd->uclass_root;
  50                new_gd->uclass_root->prev->next = new_gd->uclass_root;
  51        }
  52}
  53
  54void fix_drivers(void)
  55{
  56        struct driver *drv =
  57                ll_entry_start(struct driver, driver);
  58        const int n_ents = ll_entry_count(struct driver, driver);
  59        struct driver *entry;
  60
  61        for (entry = drv; entry != drv + n_ents; entry++) {
  62                if (entry->of_match)
  63                        entry->of_match = (const struct udevice_id *)
  64                                ((ulong)entry->of_match + gd->reloc_off);
  65                if (entry->bind)
  66                        entry->bind += gd->reloc_off;
  67                if (entry->probe)
  68                        entry->probe += gd->reloc_off;
  69                if (entry->remove)
  70                        entry->remove += gd->reloc_off;
  71                if (entry->unbind)
  72                        entry->unbind += gd->reloc_off;
  73                if (entry->of_to_plat)
  74                        entry->of_to_plat += gd->reloc_off;
  75                if (entry->child_post_bind)
  76                        entry->child_post_bind += gd->reloc_off;
  77                if (entry->child_pre_probe)
  78                        entry->child_pre_probe += gd->reloc_off;
  79                if (entry->child_post_remove)
  80                        entry->child_post_remove += gd->reloc_off;
  81                /* OPS are fixed in every uclass post_probe function */
  82                if (entry->ops)
  83                        entry->ops += gd->reloc_off;
  84        }
  85}
  86
  87void fix_uclass(void)
  88{
  89        struct uclass_driver *uclass =
  90                ll_entry_start(struct uclass_driver, uclass_driver);
  91        const int n_ents = ll_entry_count(struct uclass_driver, uclass_driver);
  92        struct uclass_driver *entry;
  93
  94        for (entry = uclass; entry != uclass + n_ents; entry++) {
  95                if (entry->post_bind)
  96                        entry->post_bind += gd->reloc_off;
  97                if (entry->pre_unbind)
  98                        entry->pre_unbind += gd->reloc_off;
  99                if (entry->pre_probe)
 100                        entry->pre_probe += gd->reloc_off;
 101                if (entry->post_probe)
 102                        entry->post_probe += gd->reloc_off;
 103                if (entry->pre_remove)
 104                        entry->pre_remove += gd->reloc_off;
 105                if (entry->child_post_bind)
 106                        entry->child_post_bind += gd->reloc_off;
 107                if (entry->child_pre_probe)
 108                        entry->child_pre_probe += gd->reloc_off;
 109                if (entry->init)
 110                        entry->init += gd->reloc_off;
 111                if (entry->destroy)
 112                        entry->destroy += gd->reloc_off;
 113                /* FIXME maybe also need to fix these ops */
 114                if (entry->ops)
 115                        entry->ops += gd->reloc_off;
 116        }
 117}
 118
 119void fix_devices(void)
 120{
 121        struct driver_info *dev =
 122                ll_entry_start(struct driver_info, driver_info);
 123        const int n_ents = ll_entry_count(struct driver_info, driver_info);
 124        struct driver_info *entry;
 125
 126        for (entry = dev; entry != dev + n_ents; entry++) {
 127                if (entry->plat)
 128                        entry->plat += gd->reloc_off;
 129        }
 130}
 131
 132int dm_init(bool of_live)
 133{
 134        int ret;
 135
 136        if (IS_ENABLED(CONFIG_OF_TRANSLATE_ZERO_SIZE_CELLS))
 137                gd->dm_flags |= GD_DM_FLG_SIZE_CELLS_0;
 138
 139        if (gd->dm_root) {
 140                dm_warn("Virtual root driver already exists!\n");
 141                return -EINVAL;
 142        }
 143        gd->uclass_root = &DM_UCLASS_ROOT_S_NON_CONST;
 144        INIT_LIST_HEAD(DM_UCLASS_ROOT_NON_CONST);
 145
 146        if (IS_ENABLED(CONFIG_NEEDS_MANUAL_RELOC)) {
 147                fix_drivers();
 148                fix_uclass();
 149                fix_devices();
 150        }
 151
 152        ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
 153        if (ret)
 154                return ret;
 155        if (CONFIG_IS_ENABLED(OF_CONTROL))
 156                dev_set_ofnode(DM_ROOT_NON_CONST, ofnode_root());
 157        ret = device_probe(DM_ROOT_NON_CONST);
 158        if (ret)
 159                return ret;
 160
 161        return 0;
 162}
 163
 164int dm_uninit(void)
 165{
 166        /* Remove non-vital devices first */
 167        device_remove(dm_root(), DM_REMOVE_NON_VITAL);
 168        device_remove(dm_root(), DM_REMOVE_NORMAL);
 169        device_unbind(dm_root());
 170        gd->dm_root = NULL;
 171
 172        return 0;
 173}
 174
 175#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
 176int dm_remove_devices_flags(uint flags)
 177{
 178        device_remove(dm_root(), flags);
 179
 180        return 0;
 181}
 182#endif
 183
 184int dm_scan_plat(bool pre_reloc_only)
 185{
 186        int ret;
 187
 188        if (CONFIG_IS_ENABLED(OF_PLATDATA)) {
 189                struct driver_rt *dyn;
 190                int n_ents;
 191
 192                n_ents = ll_entry_count(struct driver_info, driver_info);
 193                dyn = calloc(n_ents, sizeof(struct driver_rt));
 194                if (!dyn)
 195                        return -ENOMEM;
 196                gd_set_dm_driver_rt(dyn);
 197        }
 198
 199        ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only);
 200        if (ret == -ENOENT) {
 201                dm_warn("Some drivers were not found\n");
 202                ret = 0;
 203        }
 204
 205        return ret;
 206}
 207
 208#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 209/**
 210 * dm_scan_fdt_node() - Scan the device tree and bind drivers for a node
 211 *
 212 * This scans the subnodes of a device tree node and and creates a driver
 213 * for each one.
 214 *
 215 * @parent: Parent device for the devices that will be created
 216 * @node: Node to scan
 217 * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC
 218 * flag. If false bind all drivers.
 219 * @return 0 if OK, -ve on error
 220 */
 221static int dm_scan_fdt_node(struct udevice *parent, ofnode parent_node,
 222                            bool pre_reloc_only)
 223{
 224        int ret = 0, err;
 225        ofnode node;
 226
 227        if (!ofnode_valid(parent_node))
 228                return 0;
 229
 230        for (node = ofnode_first_subnode(parent_node);
 231             ofnode_valid(node);
 232             node = ofnode_next_subnode(node)) {
 233                const char *node_name = ofnode_get_name(node);
 234
 235                if (!ofnode_is_enabled(node)) {
 236                        pr_debug("   - ignoring disabled device\n");
 237                        continue;
 238                }
 239                err = lists_bind_fdt(parent, node, NULL, pre_reloc_only);
 240                if (err && !ret) {
 241                        ret = err;
 242                        debug("%s: ret=%d\n", node_name, ret);
 243                }
 244        }
 245
 246        if (ret)
 247                dm_warn("Some drivers failed to bind\n");
 248
 249        return ret;
 250}
 251
 252int dm_scan_fdt_dev(struct udevice *dev)
 253{
 254        return dm_scan_fdt_node(dev, dev_ofnode(dev),
 255                                gd->flags & GD_FLG_RELOC ? false : true);
 256}
 257
 258int dm_scan_fdt(bool pre_reloc_only)
 259{
 260        return dm_scan_fdt_node(gd->dm_root, ofnode_root(), pre_reloc_only);
 261}
 262
 263static int dm_scan_fdt_ofnode_path(const char *path, bool pre_reloc_only)
 264{
 265        ofnode node;
 266
 267        node = ofnode_path(path);
 268
 269        return dm_scan_fdt_node(gd->dm_root, node, pre_reloc_only);
 270}
 271
 272int dm_extended_scan(bool pre_reloc_only)
 273{
 274        int ret, i;
 275        const char * const nodes[] = {
 276                "/chosen",
 277                "/clocks",
 278                "/firmware"
 279        };
 280
 281        ret = dm_scan_fdt(pre_reloc_only);
 282        if (ret) {
 283                debug("dm_scan_fdt() failed: %d\n", ret);
 284                return ret;
 285        }
 286
 287        /* Some nodes aren't devices themselves but may contain some */
 288        for (i = 0; i < ARRAY_SIZE(nodes); i++) {
 289                ret = dm_scan_fdt_ofnode_path(nodes[i], pre_reloc_only);
 290                if (ret) {
 291                        debug("dm_scan_fdt() scan for %s failed: %d\n",
 292                              nodes[i], ret);
 293                        return ret;
 294                }
 295        }
 296
 297        return ret;
 298}
 299#endif
 300
 301__weak int dm_scan_other(bool pre_reloc_only)
 302{
 303        return 0;
 304}
 305
 306/**
 307 * dm_scan() - Scan tables to bind devices
 308 *
 309 * Runs through the driver_info tables and binds the devices it finds. Then runs
 310 * through the devicetree nodes. Finally calls dm_scan_other() to add any
 311 * special devices
 312 *
 313 * @pre_reloc_only: If true, bind only nodes with special devicetree properties,
 314 * or drivers with the DM_FLAG_PRE_RELOC flag. If false bind all drivers.
 315 */
 316static int dm_scan(bool pre_reloc_only)
 317{
 318        int ret;
 319
 320        ret = dm_scan_plat(pre_reloc_only);
 321        if (ret) {
 322                debug("dm_scan_plat() failed: %d\n", ret);
 323                return ret;
 324        }
 325
 326        if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
 327                ret = dm_extended_scan(pre_reloc_only);
 328                if (ret) {
 329                        debug("dm_extended_scan() failed: %d\n", ret);
 330                        return ret;
 331                }
 332        }
 333
 334        ret = dm_scan_other(pre_reloc_only);
 335        if (ret)
 336                return ret;
 337
 338        return 0;
 339}
 340
 341int dm_init_and_scan(bool pre_reloc_only)
 342{
 343        int ret;
 344
 345        ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE));
 346        if (ret) {
 347                debug("dm_init() failed: %d\n", ret);
 348                return ret;
 349        }
 350        ret = dm_scan(pre_reloc_only);
 351        if (ret) {
 352                log_debug("dm_scan() failed: %d\n", ret);
 353                return ret;
 354        }
 355
 356        return 0;
 357}
 358
 359#ifdef CONFIG_ACPIGEN
 360static int root_acpi_get_name(const struct udevice *dev, char *out_name)
 361{
 362        return acpi_copy_name(out_name, "\\_SB");
 363}
 364
 365struct acpi_ops root_acpi_ops = {
 366        .get_name       = root_acpi_get_name,
 367};
 368#endif
 369
 370/* This is the root driver - all drivers are children of this */
 371U_BOOT_DRIVER(root_driver) = {
 372        .name   = "root_driver",
 373        .id     = UCLASS_ROOT,
 374        ACPI_OPS_PTR(&root_acpi_ops)
 375};
 376
 377/* This is the root uclass */
 378UCLASS_DRIVER(root) = {
 379        .name   = "root",
 380        .id     = UCLASS_ROOT,
 381};
 382