uboot/drivers/core/ofnode.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2017 Google, Inc
   4 * Written by Simon Glass <sjg@chromium.org>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <fdtdec.h>
  10#include <fdt_support.h>
  11#include <log.h>
  12#include <malloc.h>
  13#include <linux/libfdt.h>
  14#include <dm/of_access.h>
  15#include <dm/of_addr.h>
  16#include <dm/ofnode.h>
  17#include <linux/err.h>
  18#include <linux/ioport.h>
  19#include <asm/global_data.h>
  20
  21bool ofnode_name_eq(ofnode node, const char *name)
  22{
  23        const char *node_name;
  24        size_t len;
  25
  26        assert(ofnode_valid(node));
  27
  28        node_name = ofnode_get_name(node);
  29        len = strchrnul(node_name, '@') - node_name;
  30
  31        return (strlen(name) == len) && !strncmp(node_name, name, len);
  32}
  33
  34int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
  35{
  36        return ofnode_read_u32_index(node, propname, 0, outp);
  37}
  38
  39u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
  40{
  41        assert(ofnode_valid(node));
  42        ofnode_read_u32_index(node, propname, 0, &def);
  43
  44        return def;
  45}
  46
  47int ofnode_read_u32_index(ofnode node, const char *propname, int index,
  48                          u32 *outp)
  49{
  50        const fdt32_t *cell;
  51        int len;
  52
  53        assert(ofnode_valid(node));
  54        debug("%s: %s: ", __func__, propname);
  55
  56        if (ofnode_is_np(node))
  57                return of_read_u32_index(ofnode_to_np(node), propname, index,
  58                                         outp);
  59
  60        cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
  61                           &len);
  62        if (!cell) {
  63                debug("(not found)\n");
  64                return -EINVAL;
  65        }
  66
  67        if (len < (sizeof(int) * (index + 1))) {
  68                debug("(not large enough)\n");
  69                return -EOVERFLOW;
  70        }
  71
  72        *outp = fdt32_to_cpu(cell[index]);
  73        debug("%#x (%d)\n", *outp, *outp);
  74
  75        return 0;
  76}
  77
  78u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
  79                                  u32 def)
  80{
  81        assert(ofnode_valid(node));
  82        ofnode_read_u32_index(node, propname, index, &def);
  83
  84        return def;
  85}
  86
  87int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
  88{
  89        assert(ofnode_valid(node));
  90        ofnode_read_u32(node, propname, (u32 *)&def);
  91
  92        return def;
  93}
  94
  95int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
  96{
  97        const unaligned_fdt64_t *cell;
  98        int len;
  99
 100        assert(ofnode_valid(node));
 101        debug("%s: %s: ", __func__, propname);
 102
 103        if (ofnode_is_np(node))
 104                return of_read_u64(ofnode_to_np(node), propname, outp);
 105
 106        cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
 107                           &len);
 108        if (!cell || len < sizeof(*cell)) {
 109                debug("(not found)\n");
 110                return -EINVAL;
 111        }
 112        *outp = fdt64_to_cpu(cell[0]);
 113        debug("%#llx (%lld)\n", (unsigned long long)*outp,
 114              (unsigned long long)*outp);
 115
 116        return 0;
 117}
 118
 119u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
 120{
 121        assert(ofnode_valid(node));
 122        ofnode_read_u64(node, propname, &def);
 123
 124        return def;
 125}
 126
 127bool ofnode_read_bool(ofnode node, const char *propname)
 128{
 129        const void *prop;
 130
 131        assert(ofnode_valid(node));
 132        debug("%s: %s: ", __func__, propname);
 133
 134        prop = ofnode_get_property(node, propname, NULL);
 135
 136        debug("%s\n", prop ? "true" : "false");
 137
 138        return prop ? true : false;
 139}
 140
 141const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
 142{
 143        const char *val = NULL;
 144        int len;
 145
 146        assert(ofnode_valid(node));
 147        debug("%s: %s: ", __func__, propname);
 148
 149        if (ofnode_is_np(node)) {
 150                struct property *prop = of_find_property(
 151                                ofnode_to_np(node), propname, &len);
 152
 153                if (prop) {
 154                        val = prop->value;
 155                        len = prop->length;
 156                }
 157        } else {
 158                val = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
 159                                  propname, &len);
 160        }
 161        if (!val) {
 162                debug("<not found>\n");
 163                if (sizep)
 164                        *sizep = -FDT_ERR_NOTFOUND;
 165                return NULL;
 166        }
 167        if (sizep)
 168                *sizep = len;
 169
 170        return val;
 171}
 172
 173const char *ofnode_read_string(ofnode node, const char *propname)
 174{
 175        const char *str;
 176        int len;
 177
 178        str = ofnode_read_prop(node, propname, &len);
 179        if (!str)
 180                return NULL;
 181
 182        if (strnlen(str, len) >= len) {
 183                debug("<invalid>\n");
 184                return NULL;
 185        }
 186        debug("%s\n", str);
 187
 188        return str;
 189}
 190
 191int ofnode_read_size(ofnode node, const char *propname)
 192{
 193        int len;
 194
 195        if (!ofnode_read_prop(node, propname, &len))
 196                return -EINVAL;
 197
 198        return len;
 199}
 200
 201ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
 202{
 203        ofnode subnode;
 204
 205        assert(ofnode_valid(node));
 206        debug("%s: %s: ", __func__, subnode_name);
 207
 208        if (ofnode_is_np(node)) {
 209                const struct device_node *np = ofnode_to_np(node);
 210
 211                for (np = np->child; np; np = np->sibling) {
 212                        if (!strcmp(subnode_name, np->name))
 213                                break;
 214                }
 215                subnode = np_to_ofnode(np);
 216        } else {
 217                int ooffset = fdt_subnode_offset(gd->fdt_blob,
 218                                ofnode_to_offset(node), subnode_name);
 219                subnode = offset_to_ofnode(ooffset);
 220        }
 221        debug("%s\n", ofnode_valid(subnode) ?
 222              ofnode_get_name(subnode) : "<none>");
 223
 224        return subnode;
 225}
 226
 227int ofnode_read_u32_array(ofnode node, const char *propname,
 228                          u32 *out_values, size_t sz)
 229{
 230        assert(ofnode_valid(node));
 231        debug("%s: %s: ", __func__, propname);
 232
 233        if (ofnode_is_np(node)) {
 234                return of_read_u32_array(ofnode_to_np(node), propname,
 235                                         out_values, sz);
 236        } else {
 237                return fdtdec_get_int_array(gd->fdt_blob,
 238                                            ofnode_to_offset(node), propname,
 239                                            out_values, sz);
 240        }
 241}
 242
 243#if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE)
 244bool ofnode_is_enabled(ofnode node)
 245{
 246        if (ofnode_is_np(node)) {
 247                return of_device_is_available(ofnode_to_np(node));
 248        } else {
 249                return fdtdec_get_is_enabled(gd->fdt_blob,
 250                                             ofnode_to_offset(node));
 251        }
 252}
 253
 254ofnode ofnode_first_subnode(ofnode node)
 255{
 256        assert(ofnode_valid(node));
 257        if (ofnode_is_np(node))
 258                return np_to_ofnode(node.np->child);
 259
 260        return offset_to_ofnode(
 261                fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node)));
 262}
 263
 264ofnode ofnode_next_subnode(ofnode node)
 265{
 266        assert(ofnode_valid(node));
 267        if (ofnode_is_np(node))
 268                return np_to_ofnode(node.np->sibling);
 269
 270        return offset_to_ofnode(
 271                fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node)));
 272}
 273#endif /* !DM_INLINE_OFNODE */
 274
 275ofnode ofnode_get_parent(ofnode node)
 276{
 277        ofnode parent;
 278
 279        assert(ofnode_valid(node));
 280        if (ofnode_is_np(node))
 281                parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
 282        else
 283                parent.of_offset = fdt_parent_offset(gd->fdt_blob,
 284                                                     ofnode_to_offset(node));
 285
 286        return parent;
 287}
 288
 289const char *ofnode_get_name(ofnode node)
 290{
 291        if (!ofnode_valid(node)) {
 292                debug("%s node not valid\n", __func__);
 293                return NULL;
 294        }
 295
 296        if (ofnode_is_np(node))
 297                return strrchr(node.np->full_name, '/') + 1;
 298
 299        return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL);
 300}
 301
 302int ofnode_get_path(ofnode node, char *buf, int buflen)
 303{
 304        assert(ofnode_valid(node));
 305
 306        if (ofnode_is_np(node)) {
 307                if (strlen(node.np->full_name) >= buflen)
 308                        return -ENOSPC;
 309
 310                strcpy(buf, node.np->full_name);
 311
 312                return 0;
 313        } else {
 314                int res;
 315
 316                res = fdt_get_path(gd->fdt_blob, ofnode_to_offset(node), buf,
 317                                   buflen);
 318                if (!res)
 319                        return res;
 320                else if (res == -FDT_ERR_NOSPACE)
 321                        return -ENOSPC;
 322                else
 323                        return -EINVAL;
 324        }
 325}
 326
 327ofnode ofnode_get_by_phandle(uint phandle)
 328{
 329        ofnode node;
 330
 331        if (of_live_active())
 332                node = np_to_ofnode(of_find_node_by_phandle(phandle));
 333        else
 334                node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
 335                                                            phandle);
 336
 337        return node;
 338}
 339
 340static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
 341                                               fdt_size_t *size, bool translate)
 342{
 343        int na, ns;
 344
 345        if (size)
 346                *size = FDT_SIZE_T_NONE;
 347
 348        if (ofnode_is_np(node)) {
 349                const __be32 *prop_val;
 350                u64 size64;
 351                uint flags;
 352
 353                prop_val = of_get_address(ofnode_to_np(node), index, &size64,
 354                                          &flags);
 355                if (!prop_val)
 356                        return FDT_ADDR_T_NONE;
 357
 358                if (size)
 359                        *size = size64;
 360
 361                ns = of_n_size_cells(ofnode_to_np(node));
 362
 363                if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
 364                        return of_translate_address(ofnode_to_np(node), prop_val);
 365                } else {
 366                        na = of_n_addr_cells(ofnode_to_np(node));
 367                        return of_read_number(prop_val, na);
 368                }
 369        } else {
 370                na = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
 371                ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
 372                return fdtdec_get_addr_size_fixed(gd->fdt_blob,
 373                                                  ofnode_to_offset(node), "reg",
 374                                                  index, na, ns, size,
 375                                                  translate);
 376        }
 377}
 378
 379fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
 380{
 381        return __ofnode_get_addr_size_index(node, index, size, true);
 382}
 383
 384fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index,
 385                                              fdt_size_t *size)
 386{
 387        return __ofnode_get_addr_size_index(node, index, size, false);
 388}
 389
 390fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
 391{
 392        fdt_size_t size;
 393
 394        return ofnode_get_addr_size_index(node, index, &size);
 395}
 396
 397fdt_addr_t ofnode_get_addr(ofnode node)
 398{
 399        return ofnode_get_addr_index(node, 0);
 400}
 401
 402fdt_size_t ofnode_get_size(ofnode node)
 403{
 404        fdt_size_t size;
 405
 406        ofnode_get_addr_size_index(node, 0, &size);
 407
 408        return size;
 409}
 410
 411int ofnode_stringlist_search(ofnode node, const char *property,
 412                             const char *string)
 413{
 414        if (ofnode_is_np(node)) {
 415                return of_property_match_string(ofnode_to_np(node),
 416                                                property, string);
 417        } else {
 418                int ret;
 419
 420                ret = fdt_stringlist_search(gd->fdt_blob,
 421                                            ofnode_to_offset(node), property,
 422                                            string);
 423                if (ret == -FDT_ERR_NOTFOUND)
 424                        return -ENODATA;
 425                else if (ret < 0)
 426                        return -EINVAL;
 427
 428                return ret;
 429        }
 430}
 431
 432int ofnode_read_string_index(ofnode node, const char *property, int index,
 433                             const char **outp)
 434{
 435        if (ofnode_is_np(node)) {
 436                return of_property_read_string_index(ofnode_to_np(node),
 437                                                     property, index, outp);
 438        } else {
 439                int len;
 440
 441                *outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node),
 442                                           property, index, &len);
 443                if (len < 0)
 444                        return -EINVAL;
 445                return 0;
 446        }
 447}
 448
 449int ofnode_read_string_count(ofnode node, const char *property)
 450{
 451        if (ofnode_is_np(node)) {
 452                return of_property_count_strings(ofnode_to_np(node), property);
 453        } else {
 454                return fdt_stringlist_count(gd->fdt_blob,
 455                                            ofnode_to_offset(node), property);
 456        }
 457}
 458
 459static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
 460                                            struct ofnode_phandle_args *out)
 461{
 462        assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
 463        out->node = offset_to_ofnode(in->node);
 464        out->args_count = in->args_count;
 465        memcpy(out->args, in->args, sizeof(out->args));
 466}
 467
 468static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
 469                                        struct ofnode_phandle_args *out)
 470{
 471        assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
 472        out->node = np_to_ofnode(in->np);
 473        out->args_count = in->args_count;
 474        memcpy(out->args, in->args, sizeof(out->args));
 475}
 476
 477int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
 478                                   const char *cells_name, int cell_count,
 479                                   int index,
 480                                   struct ofnode_phandle_args *out_args)
 481{
 482        if (ofnode_is_np(node)) {
 483                struct of_phandle_args args;
 484                int ret;
 485
 486                ret = of_parse_phandle_with_args(ofnode_to_np(node),
 487                                                 list_name, cells_name,
 488                                                 cell_count, index,
 489                                                 &args);
 490                if (ret)
 491                        return ret;
 492                ofnode_from_of_phandle_args(&args, out_args);
 493        } else {
 494                struct fdtdec_phandle_args args;
 495                int ret;
 496
 497                ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
 498                                                     ofnode_to_offset(node),
 499                                                     list_name, cells_name,
 500                                                     cell_count, index, &args);
 501                if (ret)
 502                        return ret;
 503                ofnode_from_fdtdec_phandle_args(&args, out_args);
 504        }
 505
 506        return 0;
 507}
 508
 509int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
 510                                   const char *cells_name, int cell_count)
 511{
 512        if (ofnode_is_np(node))
 513                return of_count_phandle_with_args(ofnode_to_np(node),
 514                                list_name, cells_name, cell_count);
 515        else
 516                return fdtdec_parse_phandle_with_args(gd->fdt_blob,
 517                                ofnode_to_offset(node), list_name, cells_name,
 518                                cell_count, -1, NULL);
 519}
 520
 521ofnode ofnode_path(const char *path)
 522{
 523        if (of_live_active())
 524                return np_to_ofnode(of_find_node_by_path(path));
 525        else
 526                return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
 527}
 528
 529const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
 530{
 531        ofnode chosen_node;
 532
 533        chosen_node = ofnode_path("/chosen");
 534
 535        return ofnode_read_prop(chosen_node, propname, sizep);
 536}
 537
 538const char *ofnode_read_chosen_string(const char *propname)
 539{
 540        return ofnode_read_chosen_prop(propname, NULL);
 541}
 542
 543ofnode ofnode_get_chosen_node(const char *name)
 544{
 545        const char *prop;
 546
 547        prop = ofnode_read_chosen_prop(name, NULL);
 548        if (!prop)
 549                return ofnode_null();
 550
 551        return ofnode_path(prop);
 552}
 553
 554const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
 555{
 556        ofnode node;
 557
 558        node = ofnode_path("/aliases");
 559
 560        return ofnode_read_prop(node, propname, sizep);
 561}
 562
 563ofnode ofnode_get_aliases_node(const char *name)
 564{
 565        const char *prop;
 566
 567        prop = ofnode_read_aliases_prop(name, NULL);
 568        if (!prop)
 569                return ofnode_null();
 570
 571        debug("%s: node_path: %s\n", __func__, prop);
 572
 573        return ofnode_path(prop);
 574}
 575
 576int ofnode_get_child_count(ofnode parent)
 577{
 578        ofnode child;
 579        int num = 0;
 580
 581        ofnode_for_each_subnode(child, parent)
 582                num++;
 583
 584        return num;
 585}
 586
 587static int decode_timing_property(ofnode node, const char *name,
 588                                  struct timing_entry *result)
 589{
 590        int length, ret = 0;
 591
 592        length = ofnode_read_size(node, name);
 593        if (length < 0) {
 594                debug("%s: could not find property %s\n",
 595                      ofnode_get_name(node), name);
 596                return length;
 597        }
 598
 599        if (length == sizeof(u32)) {
 600                result->typ = ofnode_read_u32_default(node, name, 0);
 601                result->min = result->typ;
 602                result->max = result->typ;
 603        } else {
 604                ret = ofnode_read_u32_array(node, name, &result->min, 3);
 605        }
 606
 607        return ret;
 608}
 609
 610int ofnode_decode_display_timing(ofnode parent, int index,
 611                                 struct display_timing *dt)
 612{
 613        int i;
 614        ofnode timings, node;
 615        u32 val = 0;
 616        int ret = 0;
 617
 618        timings = ofnode_find_subnode(parent, "display-timings");
 619        if (!ofnode_valid(timings))
 620                return -EINVAL;
 621
 622        i = 0;
 623        ofnode_for_each_subnode(node, timings) {
 624                if (i++ == index)
 625                        break;
 626        }
 627
 628        if (!ofnode_valid(node))
 629                return -EINVAL;
 630
 631        memset(dt, 0, sizeof(*dt));
 632
 633        ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
 634        ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
 635        ret |= decode_timing_property(node, "hactive", &dt->hactive);
 636        ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
 637        ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
 638        ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
 639        ret |= decode_timing_property(node, "vactive", &dt->vactive);
 640        ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
 641        ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
 642
 643        dt->flags = 0;
 644        val = ofnode_read_u32_default(node, "vsync-active", -1);
 645        if (val != -1) {
 646                dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
 647                                DISPLAY_FLAGS_VSYNC_LOW;
 648        }
 649        val = ofnode_read_u32_default(node, "hsync-active", -1);
 650        if (val != -1) {
 651                dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
 652                                DISPLAY_FLAGS_HSYNC_LOW;
 653        }
 654        val = ofnode_read_u32_default(node, "de-active", -1);
 655        if (val != -1) {
 656                dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
 657                                DISPLAY_FLAGS_DE_LOW;
 658        }
 659        val = ofnode_read_u32_default(node, "pixelclk-active", -1);
 660        if (val != -1) {
 661                dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
 662                                DISPLAY_FLAGS_PIXDATA_NEGEDGE;
 663        }
 664
 665        if (ofnode_read_bool(node, "interlaced"))
 666                dt->flags |= DISPLAY_FLAGS_INTERLACED;
 667        if (ofnode_read_bool(node, "doublescan"))
 668                dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
 669        if (ofnode_read_bool(node, "doubleclk"))
 670                dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
 671
 672        return ret;
 673}
 674
 675const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
 676{
 677        if (ofnode_is_np(node))
 678                return of_get_property(ofnode_to_np(node), propname, lenp);
 679        else
 680                return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
 681                                   propname, lenp);
 682}
 683
 684int ofnode_get_first_property(ofnode node, struct ofprop *prop)
 685{
 686        prop->node = node;
 687
 688        if (ofnode_is_np(node)) {
 689                prop->prop = of_get_first_property(ofnode_to_np(prop->node));
 690                if (!prop->prop)
 691                        return -FDT_ERR_NOTFOUND;
 692        } else {
 693                prop->offset =
 694                        fdt_first_property_offset(gd->fdt_blob,
 695                                                  ofnode_to_offset(prop->node));
 696                if (prop->offset < 0)
 697                        return prop->offset;
 698        }
 699
 700        return 0;
 701}
 702
 703int ofnode_get_next_property(struct ofprop *prop)
 704{
 705        if (ofnode_is_np(prop->node)) {
 706                prop->prop = of_get_next_property(ofnode_to_np(prop->node),
 707                                                  prop->prop);
 708                if (!prop->prop)
 709                        return -FDT_ERR_NOTFOUND;
 710        } else {
 711                prop->offset = fdt_next_property_offset(gd->fdt_blob,
 712                                                        prop->offset);
 713                if (prop->offset  < 0)
 714                        return prop->offset;
 715        }
 716
 717        return 0;
 718}
 719
 720const void *ofnode_get_property_by_prop(const struct ofprop *prop,
 721                                        const char **propname, int *lenp)
 722{
 723        if (ofnode_is_np(prop->node))
 724                return of_get_property_by_prop(ofnode_to_np(prop->node),
 725                                               prop->prop, propname, lenp);
 726        else
 727                return fdt_getprop_by_offset(gd->fdt_blob,
 728                                             prop->offset,
 729                                             propname, lenp);
 730}
 731
 732bool ofnode_is_available(ofnode node)
 733{
 734        if (ofnode_is_np(node))
 735                return of_device_is_available(ofnode_to_np(node));
 736        else
 737                return fdtdec_get_is_enabled(gd->fdt_blob,
 738                                             ofnode_to_offset(node));
 739}
 740
 741fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
 742                                fdt_size_t *sizep)
 743{
 744        if (ofnode_is_np(node)) {
 745                int na, ns;
 746                int psize;
 747                const struct device_node *np = ofnode_to_np(node);
 748                const __be32 *prop = of_get_property(np, property, &psize);
 749
 750                if (!prop)
 751                        return FDT_ADDR_T_NONE;
 752                na = of_n_addr_cells(np);
 753                ns = of_n_size_cells(np);
 754                *sizep = of_read_number(prop + na, ns);
 755
 756                if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
 757                        return of_translate_address(np, prop);
 758                else
 759                        return of_read_number(prop, na);
 760        } else {
 761                return fdtdec_get_addr_size(gd->fdt_blob,
 762                                            ofnode_to_offset(node), property,
 763                                            sizep);
 764        }
 765}
 766
 767const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
 768                                        size_t sz)
 769{
 770        if (ofnode_is_np(node)) {
 771                const struct device_node *np = ofnode_to_np(node);
 772                int psize;
 773                const __be32 *prop = of_get_property(np, propname, &psize);
 774
 775                if (!prop || sz != psize)
 776                        return NULL;
 777                return (uint8_t *)prop;
 778
 779        } else {
 780                return fdtdec_locate_byte_array(gd->fdt_blob,
 781                                ofnode_to_offset(node), propname, sz);
 782        }
 783}
 784
 785int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
 786                         const char *propname, struct fdt_pci_addr *addr)
 787{
 788        const fdt32_t *cell;
 789        int len;
 790        int ret = -ENOENT;
 791
 792        debug("%s: %s: ", __func__, propname);
 793
 794        /*
 795         * If we follow the pci bus bindings strictly, we should check
 796         * the value of the node's parent node's #address-cells and
 797         * #size-cells. They need to be 3 and 2 accordingly. However,
 798         * for simplicity we skip the check here.
 799         */
 800        cell = ofnode_get_property(node, propname, &len);
 801        if (!cell)
 802                goto fail;
 803
 804        if ((len % FDT_PCI_REG_SIZE) == 0) {
 805                int num = len / FDT_PCI_REG_SIZE;
 806                int i;
 807
 808                for (i = 0; i < num; i++) {
 809                        debug("pci address #%d: %08lx %08lx %08lx\n", i,
 810                              (ulong)fdt32_to_cpu(cell[0]),
 811                              (ulong)fdt32_to_cpu(cell[1]),
 812                              (ulong)fdt32_to_cpu(cell[2]));
 813                        if ((fdt32_to_cpu(*cell) & type) == type) {
 814                                addr->phys_hi = fdt32_to_cpu(cell[0]);
 815                                addr->phys_mid = fdt32_to_cpu(cell[1]);
 816                                addr->phys_lo = fdt32_to_cpu(cell[2]);
 817                                break;
 818                        }
 819
 820                        cell += (FDT_PCI_ADDR_CELLS +
 821                                 FDT_PCI_SIZE_CELLS);
 822                }
 823
 824                if (i == num) {
 825                        ret = -ENXIO;
 826                        goto fail;
 827                }
 828
 829                return 0;
 830        }
 831
 832        ret = -EINVAL;
 833
 834fail:
 835        debug("(not found)\n");
 836        return ret;
 837}
 838
 839int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
 840{
 841        const char *list, *end;
 842        int len;
 843
 844        list = ofnode_get_property(node, "compatible", &len);
 845        if (!list)
 846                return -ENOENT;
 847
 848        end = list + len;
 849        while (list < end) {
 850                len = strlen(list);
 851                if (len >= strlen("pciVVVV,DDDD")) {
 852                        char *s = strstr(list, "pci");
 853
 854                        /*
 855                         * check if the string is something like pciVVVV,DDDD.RR
 856                         * or just pciVVVV,DDDD
 857                         */
 858                        if (s && s[7] == ',' &&
 859                            (s[12] == '.' || s[12] == 0)) {
 860                                s += 3;
 861                                *vendor = simple_strtol(s, NULL, 16);
 862
 863                                s += 5;
 864                                *device = simple_strtol(s, NULL, 16);
 865
 866                                return 0;
 867                        }
 868                }
 869                list += (len + 1);
 870        }
 871
 872        return -ENOENT;
 873}
 874
 875int ofnode_read_addr_cells(ofnode node)
 876{
 877        if (ofnode_is_np(node)) {
 878                return of_n_addr_cells(ofnode_to_np(node));
 879        } else {
 880                int parent = fdt_parent_offset(gd->fdt_blob,
 881                                               ofnode_to_offset(node));
 882
 883                return fdt_address_cells(gd->fdt_blob, parent);
 884        }
 885}
 886
 887int ofnode_read_size_cells(ofnode node)
 888{
 889        if (ofnode_is_np(node)) {
 890                return of_n_size_cells(ofnode_to_np(node));
 891        } else {
 892                int parent = fdt_parent_offset(gd->fdt_blob,
 893                                               ofnode_to_offset(node));
 894
 895                return fdt_size_cells(gd->fdt_blob, parent);
 896        }
 897}
 898
 899int ofnode_read_simple_addr_cells(ofnode node)
 900{
 901        if (ofnode_is_np(node))
 902                return of_simple_addr_cells(ofnode_to_np(node));
 903        else
 904                return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
 905}
 906
 907int ofnode_read_simple_size_cells(ofnode node)
 908{
 909        if (ofnode_is_np(node))
 910                return of_simple_size_cells(ofnode_to_np(node));
 911        else
 912                return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
 913}
 914
 915bool ofnode_pre_reloc(ofnode node)
 916{
 917#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
 918        /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
 919         * had property dm-pre-reloc or u-boot,dm-spl/tpl.
 920         * They are removed in final dtb (fdtgrep 2nd pass)
 921         */
 922        return true;
 923#else
 924        if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
 925                return true;
 926        if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
 927                return true;
 928
 929        /*
 930         * In regular builds individual spl and tpl handling both
 931         * count as handled pre-relocation for later second init.
 932         */
 933        if (ofnode_read_bool(node, "u-boot,dm-spl") ||
 934            ofnode_read_bool(node, "u-boot,dm-tpl"))
 935                return true;
 936
 937        return false;
 938#endif
 939}
 940
 941int ofnode_read_resource(ofnode node, uint index, struct resource *res)
 942{
 943        if (ofnode_is_np(node)) {
 944                return of_address_to_resource(ofnode_to_np(node), index, res);
 945        } else {
 946                struct fdt_resource fres;
 947                int ret;
 948
 949                ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
 950                                       "reg", index, &fres);
 951                if (ret < 0)
 952                        return -EINVAL;
 953                memset(res, '\0', sizeof(*res));
 954                res->start = fres.start;
 955                res->end = fres.end;
 956
 957                return 0;
 958        }
 959}
 960
 961int ofnode_read_resource_byname(ofnode node, const char *name,
 962                                struct resource *res)
 963{
 964        int index;
 965
 966        index = ofnode_stringlist_search(node, "reg-names", name);
 967        if (index < 0)
 968                return index;
 969
 970        return ofnode_read_resource(node, index, res);
 971}
 972
 973u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
 974{
 975        if (ofnode_is_np(node))
 976                return of_translate_address(ofnode_to_np(node), in_addr);
 977        else
 978                return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
 979}
 980
 981u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
 982{
 983        if (ofnode_is_np(node))
 984                return of_translate_dma_address(ofnode_to_np(node), in_addr);
 985        else
 986                return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
 987}
 988
 989int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
 990{
 991        if (ofnode_is_np(node))
 992                return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
 993        else
 994                return fdt_get_dma_range(gd->fdt_blob, ofnode_to_offset(node),
 995                                         cpu, bus, size);
 996}
 997
 998int ofnode_device_is_compatible(ofnode node, const char *compat)
 999{
1000        if (ofnode_is_np(node))
1001                return of_device_is_compatible(ofnode_to_np(node), compat,
1002                                               NULL, NULL);
1003        else
1004                return !fdt_node_check_compatible(gd->fdt_blob,
1005                                                  ofnode_to_offset(node),
1006                                                  compat);
1007}
1008
1009ofnode ofnode_by_compatible(ofnode from, const char *compat)
1010{
1011        if (of_live_active()) {
1012                return np_to_ofnode(of_find_compatible_node(
1013                        (struct device_node *)ofnode_to_np(from), NULL,
1014                        compat));
1015        } else {
1016                return offset_to_ofnode(fdt_node_offset_by_compatible(
1017                                gd->fdt_blob, ofnode_to_offset(from), compat));
1018        }
1019}
1020
1021ofnode ofnode_by_prop_value(ofnode from, const char *propname,
1022                            const void *propval, int proplen)
1023{
1024        if (of_live_active()) {
1025                return np_to_ofnode(of_find_node_by_prop_value(
1026                        (struct device_node *)ofnode_to_np(from), propname,
1027                        propval, proplen));
1028        } else {
1029                return offset_to_ofnode(fdt_node_offset_by_prop_value(
1030                                gd->fdt_blob, ofnode_to_offset(from),
1031                                propname, propval, proplen));
1032        }
1033}
1034
1035int ofnode_write_prop(ofnode node, const char *propname, int len,
1036                      const void *value)
1037{
1038        const struct device_node *np = ofnode_to_np(node);
1039        struct property *pp;
1040        struct property *pp_last = NULL;
1041        struct property *new;
1042
1043        if (!of_live_active())
1044                return -ENOSYS;
1045
1046        if (!np)
1047                return -EINVAL;
1048
1049        for (pp = np->properties; pp; pp = pp->next) {
1050                if (strcmp(pp->name, propname) == 0) {
1051                        /* Property exists -> change value */
1052                        pp->value = (void *)value;
1053                        pp->length = len;
1054                        return 0;
1055                }
1056                pp_last = pp;
1057        }
1058
1059        if (!pp_last)
1060                return -ENOENT;
1061
1062        /* Property does not exist -> append new property */
1063        new = malloc(sizeof(struct property));
1064        if (!new)
1065                return -ENOMEM;
1066
1067        new->name = strdup(propname);
1068        if (!new->name) {
1069                free(new);
1070                return -ENOMEM;
1071        }
1072
1073        new->value = (void *)value;
1074        new->length = len;
1075        new->next = NULL;
1076
1077        pp_last->next = new;
1078
1079        return 0;
1080}
1081
1082int ofnode_write_string(ofnode node, const char *propname, const char *value)
1083{
1084        if (!of_live_active())
1085                return -ENOSYS;
1086
1087        assert(ofnode_valid(node));
1088
1089        debug("%s: %s = %s", __func__, propname, value);
1090
1091        return ofnode_write_prop(node, propname, strlen(value) + 1, value);
1092}
1093
1094int ofnode_set_enabled(ofnode node, bool value)
1095{
1096        if (!of_live_active())
1097                return -ENOSYS;
1098
1099        assert(ofnode_valid(node));
1100
1101        if (value)
1102                return ofnode_write_string(node, "status", "okay");
1103        else
1104                return ofnode_write_string(node, "status", "disabled");
1105}
1106
1107bool ofnode_conf_read_bool(const char *prop_name)
1108{
1109        ofnode node;
1110
1111        node = ofnode_path("/config");
1112        if (!ofnode_valid(node))
1113                return false;
1114
1115        return ofnode_read_bool(node, prop_name);
1116}
1117
1118int ofnode_conf_read_int(const char *prop_name, int default_val)
1119{
1120        ofnode node;
1121
1122        node = ofnode_path("/config");
1123        if (!ofnode_valid(node))
1124                return default_val;
1125
1126        return ofnode_read_u32_default(node, prop_name, default_val);
1127}
1128
1129const char *ofnode_conf_read_str(const char *prop_name)
1130{
1131        ofnode node;
1132
1133        node = ofnode_path("/config");
1134        if (!ofnode_valid(node))
1135                return NULL;
1136
1137        return ofnode_read_string(node, prop_name);
1138}
1139