1 /* 2 * Copyright (c) 2017 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <fdtdec.h> 11 #include <fdt_support.h> 12 #include <linux/libfdt.h> 13 #include <dm/of_access.h> 14 #include <dm/of_addr.h> 15 #include <dm/ofnode.h> 16 #include <linux/err.h> 17 #include <linux/ioport.h> 18 19 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp) 20 { 21 assert(ofnode_valid(node)); 22 debug("%s: %s: ", __func__, propname); 23 24 if (ofnode_is_np(node)) { 25 return of_read_u32(ofnode_to_np(node), propname, outp); 26 } else { 27 const fdt32_t *cell; 28 int len; 29 30 cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 31 propname, &len); 32 if (!cell || len < sizeof(int)) { 33 debug("(not found)\n"); 34 return -EINVAL; 35 } 36 *outp = fdt32_to_cpu(cell[0]); 37 } 38 debug("%#x (%d)\n", *outp, *outp); 39 40 return 0; 41 } 42 43 int ofnode_read_u32_default(ofnode node, const char *propname, u32 def) 44 { 45 assert(ofnode_valid(node)); 46 ofnode_read_u32(node, propname, &def); 47 48 return def; 49 } 50 51 int ofnode_read_s32_default(ofnode node, const char *propname, s32 def) 52 { 53 assert(ofnode_valid(node)); 54 ofnode_read_u32(node, propname, (u32 *)&def); 55 56 return def; 57 } 58 59 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp) 60 { 61 assert(ofnode_valid(node)); 62 debug("%s: %s: ", __func__, propname); 63 64 if (ofnode_is_np(node)) { 65 return of_property_read_u64(ofnode_to_np(node), propname, outp); 66 } else { 67 printf("%s: not implement\n", __func__); 68 return -EINVAL; 69 } 70 71 return 0; 72 } 73 74 bool ofnode_read_bool(ofnode node, const char *propname) 75 { 76 const void *prop; 77 78 assert(ofnode_valid(node)); 79 debug("%s: %s: ", __func__, propname); 80 81 prop = ofnode_get_property(node, propname, NULL); 82 83 debug("%s\n", prop ? "true" : "false"); 84 85 return prop ? true : false; 86 } 87 88 const char *ofnode_read_string(ofnode node, const char *propname) 89 { 90 const char *str = NULL; 91 int len = -1; 92 93 assert(ofnode_valid(node)); 94 debug("%s: %s: ", __func__, propname); 95 96 if (ofnode_is_np(node)) { 97 struct property *prop = of_find_property( 98 ofnode_to_np(node), propname, NULL); 99 100 if (prop) { 101 str = prop->value; 102 len = prop->length; 103 } 104 } else { 105 str = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 106 propname, &len); 107 } 108 if (!str) { 109 debug("<not found>\n"); 110 return NULL; 111 } 112 if (strnlen(str, len) >= len) { 113 debug("<invalid>\n"); 114 return NULL; 115 } 116 debug("%s\n", str); 117 118 return str; 119 } 120 121 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) 122 { 123 ofnode subnode; 124 125 assert(ofnode_valid(node)); 126 debug("%s: %s: ", __func__, subnode_name); 127 128 if (ofnode_is_np(node)) { 129 const struct device_node *np = ofnode_to_np(node); 130 131 for (np = np->child; np; np = np->sibling) { 132 if (!strcmp(subnode_name, np->name)) 133 break; 134 } 135 subnode = np_to_ofnode(np); 136 } else { 137 int ooffset = fdt_subnode_offset(gd->fdt_blob, 138 ofnode_to_offset(node), subnode_name); 139 subnode = offset_to_ofnode(ooffset); 140 } 141 debug("%s\n", ofnode_valid(subnode) ? 142 ofnode_get_name(subnode) : "<none>"); 143 144 return subnode; 145 } 146 147 int ofnode_read_u32_array(ofnode node, const char *propname, 148 u32 *out_values, size_t sz) 149 { 150 assert(ofnode_valid(node)); 151 debug("%s: %s: ", __func__, propname); 152 153 if (ofnode_is_np(node)) { 154 return of_read_u32_array(ofnode_to_np(node), propname, 155 out_values, sz); 156 } else { 157 return fdtdec_get_int_array(gd->fdt_blob, 158 ofnode_to_offset(node), propname, 159 out_values, sz); 160 } 161 } 162 163 int ofnode_write_u32_array(ofnode node, const char *propname, 164 u32 *values, size_t sz) 165 { 166 assert(ofnode_valid(node)); 167 debug("%s: %s: ", __func__, propname); 168 169 if (ofnode_is_np(node)) { 170 return of_write_u32_array(ofnode_to_np(node), propname, 171 values, sz); 172 } else { 173 return fdt_setprop((void *)gd->fdt_blob, ofnode_to_offset(node), 174 propname, values, sz); 175 } 176 } 177 178 ofnode ofnode_first_subnode(ofnode node) 179 { 180 assert(ofnode_valid(node)); 181 if (ofnode_is_np(node)) 182 return np_to_ofnode(node.np->child); 183 184 return offset_to_ofnode( 185 fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node))); 186 } 187 188 ofnode ofnode_next_subnode(ofnode node) 189 { 190 assert(ofnode_valid(node)); 191 if (ofnode_is_np(node)) 192 return np_to_ofnode(node.np->sibling); 193 194 return offset_to_ofnode( 195 fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node))); 196 } 197 198 ofnode ofnode_get_parent(ofnode node) 199 { 200 ofnode parent; 201 202 assert(ofnode_valid(node)); 203 if (ofnode_is_np(node)) 204 parent = np_to_ofnode(of_get_parent(ofnode_to_np(node))); 205 else 206 parent.of_offset = fdt_parent_offset(gd->fdt_blob, 207 ofnode_to_offset(node)); 208 209 return parent; 210 } 211 212 const char *ofnode_get_name(ofnode node) 213 { 214 if(!ofnode_valid(node)){ 215 debug("%s node not valid\n", __func__); 216 return NULL; 217 } 218 if (ofnode_is_np(node)) 219 return strrchr(node.np->full_name, '/') + 1; 220 221 return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL); 222 } 223 224 ofnode ofnode_get_by_phandle(uint phandle) 225 { 226 ofnode node; 227 228 if (of_live_active()) 229 node = np_to_ofnode(of_find_node_by_phandle(phandle)); 230 else 231 node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob, 232 phandle); 233 234 return node; 235 } 236 237 int ofnode_read_size(ofnode node, const char *propname) 238 { 239 int len; 240 241 if (ofnode_is_np(node)) { 242 struct property *prop = of_find_property( 243 ofnode_to_np(node), propname, NULL); 244 245 if (prop) 246 return prop->length; 247 } else { 248 if (fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, 249 &len)) 250 return len; 251 } 252 253 return -EINVAL; 254 } 255 256 fdt_addr_t ofnode_get_addr_index(ofnode node, int index) 257 { 258 if (ofnode_is_np(node)) { 259 const __be32 *prop_val; 260 uint flags; 261 u64 size; 262 int na; 263 264 prop_val = of_get_address(ofnode_to_np(node), index, &size, 265 &flags); 266 if (!prop_val) 267 return FDT_ADDR_T_NONE; 268 na = of_n_addr_cells(ofnode_to_np(node)); 269 return of_read_number(prop_val, na); 270 } else { 271 return fdt_get_base_address(gd->fdt_blob, 272 ofnode_to_offset(node)); 273 } 274 275 return FDT_ADDR_T_NONE; 276 } 277 278 fdt_addr_t ofnode_get_addr(ofnode node) 279 { 280 return ofnode_get_addr_index(node, 0); 281 } 282 283 int ofnode_stringlist_search(ofnode node, const char *property, 284 const char *string) 285 { 286 if (ofnode_is_np(node)) { 287 return of_property_match_string(ofnode_to_np(node), 288 property, string); 289 } else { 290 int ret; 291 292 ret = fdt_stringlist_search(gd->fdt_blob, 293 ofnode_to_offset(node), property, 294 string); 295 if (ret == -FDT_ERR_NOTFOUND) 296 return -ENODATA; 297 else if (ret < 0) 298 return -EINVAL; 299 300 return ret; 301 } 302 } 303 304 int ofnode_read_string_index(ofnode node, const char *property, int index, 305 const char **outp) 306 { 307 if (ofnode_is_np(node)) { 308 return of_property_read_string_index(ofnode_to_np(node), 309 property, index, outp); 310 } else { 311 int len; 312 313 *outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node), 314 property, index, &len); 315 if (len < 0) 316 return -EINVAL; 317 return 0; 318 } 319 } 320 321 int ofnode_read_string_count(ofnode node, const char *property) 322 { 323 if (ofnode_is_np(node)) { 324 return of_property_count_strings(ofnode_to_np(node), property); 325 } else { 326 return fdt_stringlist_count(gd->fdt_blob, 327 ofnode_to_offset(node), property); 328 } 329 } 330 331 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in, 332 struct ofnode_phandle_args *out) 333 { 334 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 335 out->node = offset_to_ofnode(in->node); 336 out->args_count = in->args_count; 337 memcpy(out->args, in->args, sizeof(out->args)); 338 } 339 340 static void ofnode_from_of_phandle_args(struct of_phandle_args *in, 341 struct ofnode_phandle_args *out) 342 { 343 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 344 out->node = np_to_ofnode(in->np); 345 out->args_count = in->args_count; 346 memcpy(out->args, in->args, sizeof(out->args)); 347 } 348 349 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, 350 const char *cells_name, int cell_count, 351 int index, 352 struct ofnode_phandle_args *out_args) 353 { 354 if (ofnode_is_np(node)) { 355 struct of_phandle_args args; 356 int ret; 357 358 ret = of_parse_phandle_with_args(ofnode_to_np(node), 359 list_name, cells_name, index, &args); 360 if (ret) 361 return ret; 362 ofnode_from_of_phandle_args(&args, out_args); 363 } else { 364 struct fdtdec_phandle_args args; 365 int ret; 366 367 ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, 368 ofnode_to_offset(node), list_name, cells_name, 369 cell_count, index, &args); 370 if (ret) 371 return ret; 372 ofnode_from_fdtdec_phandle_args(&args, out_args); 373 } 374 375 return 0; 376 } 377 378 int ofnode_count_phandle_with_args(ofnode node, const char *list_name, 379 const char *cells_name) 380 { 381 if (ofnode_is_np(node)) 382 return of_count_phandle_with_args(ofnode_to_np(node), 383 list_name, cells_name); 384 else 385 return fdtdec_parse_phandle_with_args(gd->fdt_blob, 386 ofnode_to_offset(node), list_name, cells_name, 387 0, -1, NULL); 388 } 389 390 ofnode ofnode_path(const char *path) 391 { 392 if (of_live_active()) 393 return np_to_ofnode(of_find_node_by_path(path)); 394 else 395 return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path)); 396 } 397 398 const char *ofnode_get_chosen_prop(const char *name) 399 { 400 ofnode chosen_node; 401 402 chosen_node = ofnode_path("/chosen"); 403 404 return ofnode_read_string(chosen_node, name); 405 } 406 407 ofnode ofnode_get_chosen_node(const char *name) 408 { 409 const char *prop; 410 411 prop = ofnode_get_chosen_prop(name); 412 if (!prop) 413 return ofnode_null(); 414 415 return ofnode_path(prop); 416 } 417 418 static int decode_timing_property(ofnode node, const char *name, 419 struct timing_entry *result) 420 { 421 int length, ret = 0; 422 423 length = ofnode_read_size(node, name); 424 if (length < 0) { 425 debug("%s: could not find property %s\n", 426 ofnode_get_name(node), name); 427 return length; 428 } 429 430 if (length == sizeof(u32)) { 431 result->typ = ofnode_read_u32_default(node, name, 0); 432 result->min = result->typ; 433 result->max = result->typ; 434 } else { 435 ret = ofnode_read_u32_array(node, name, &result->min, 3); 436 } 437 438 return ret; 439 } 440 441 int ofnode_decode_display_timing(ofnode parent, int index, 442 struct display_timing *dt) 443 { 444 int i; 445 ofnode timings, node; 446 u32 val = 0; 447 int ret = 0; 448 449 timings = ofnode_find_subnode(parent, "display-timings"); 450 if (!ofnode_valid(timings)) 451 return -EINVAL; 452 453 i = 0; 454 ofnode_for_each_subnode(node, timings) { 455 if (i++ == index) 456 break; 457 } 458 459 if (!ofnode_valid(node)) 460 return -EINVAL; 461 462 memset(dt, 0, sizeof(*dt)); 463 464 ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch); 465 ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch); 466 ret |= decode_timing_property(node, "hactive", &dt->hactive); 467 ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len); 468 ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch); 469 ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch); 470 ret |= decode_timing_property(node, "vactive", &dt->vactive); 471 ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len); 472 ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock); 473 474 dt->flags = 0; 475 val = ofnode_read_u32_default(node, "vsync-active", -1); 476 if (val != -1) { 477 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : 478 DISPLAY_FLAGS_VSYNC_LOW; 479 } 480 val = ofnode_read_u32_default(node, "hsync-active", -1); 481 if (val != -1) { 482 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : 483 DISPLAY_FLAGS_HSYNC_LOW; 484 } 485 val = ofnode_read_u32_default(node, "de-active", -1); 486 if (val != -1) { 487 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : 488 DISPLAY_FLAGS_DE_LOW; 489 } 490 val = ofnode_read_u32_default(node, "pixelclk-active", -1); 491 if (val != -1) { 492 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : 493 DISPLAY_FLAGS_PIXDATA_NEGEDGE; 494 } 495 496 if (ofnode_read_bool(node, "interlaced")) 497 dt->flags |= DISPLAY_FLAGS_INTERLACED; 498 if (ofnode_read_bool(node, "doublescan")) 499 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; 500 if (ofnode_read_bool(node, "doubleclk")) 501 dt->flags |= DISPLAY_FLAGS_DOUBLECLK; 502 503 return ret; 504 } 505 506 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp) 507 { 508 if (ofnode_is_np(node)) 509 return of_get_property(ofnode_to_np(node), propname, lenp); 510 else 511 return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 512 propname, lenp); 513 } 514 515 int ofnode_get_first_property(ofnode node, struct ofprop *prop) 516 { 517 prop->node = node; 518 519 if (ofnode_is_np(node)) { 520 prop->prop = of_get_first_property(ofnode_to_np(prop->node)); 521 if (!prop->prop) 522 return -FDT_ERR_NOTFOUND; 523 } else { 524 prop->offset = 525 fdt_first_property_offset(gd->fdt_blob, 526 ofnode_to_offset(prop->node)); 527 if (prop->offset < 0) 528 return prop->offset; 529 } 530 531 return 0; 532 } 533 534 int ofnode_get_next_property(struct ofprop *prop) 535 { 536 if (ofnode_is_np(prop->node)) { 537 prop->prop = of_get_next_property(ofnode_to_np(prop->node), 538 prop->prop); 539 if (!prop->prop) 540 return -FDT_ERR_NOTFOUND; 541 } else { 542 prop->offset = fdt_next_property_offset(gd->fdt_blob, 543 prop->offset); 544 if (prop->offset < 0) 545 return prop->offset; 546 } 547 548 return 0; 549 } 550 551 const void *ofnode_get_property_by_prop(const struct ofprop *prop, 552 const char **propname, int *lenp) 553 { 554 if (ofnode_is_np(prop->node)) 555 return of_get_property_by_prop(ofnode_to_np(prop->node), 556 prop->prop, propname, lenp); 557 else 558 return fdt_getprop_by_offset(gd->fdt_blob, 559 prop->offset, 560 propname, lenp); 561 } 562 563 bool ofnode_is_available(ofnode node) 564 { 565 if (ofnode_is_np(node)) 566 return of_device_is_available(ofnode_to_np(node)); 567 else 568 return fdtdec_get_is_enabled(gd->fdt_blob, 569 ofnode_to_offset(node)); 570 } 571 572 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, 573 fdt_size_t *sizep) 574 { 575 if (ofnode_is_np(node)) { 576 int na, ns; 577 int psize; 578 const struct device_node *np = ofnode_to_np(node); 579 const __be32 *prop = of_get_property(np, property, &psize); 580 581 if (!prop) 582 return FDT_ADDR_T_NONE; 583 na = of_n_addr_cells(np); 584 ns = of_n_addr_cells(np); 585 *sizep = of_read_number(prop + na, ns); 586 return of_read_number(prop, na); 587 } else { 588 return fdtdec_get_addr_size(gd->fdt_blob, 589 ofnode_to_offset(node), property, 590 sizep); 591 } 592 } 593 594 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, 595 size_t sz) 596 { 597 if (ofnode_is_np(node)) { 598 const struct device_node *np = ofnode_to_np(node); 599 int psize; 600 const __be32 *prop = of_get_property(np, propname, &psize); 601 602 if (!prop || sz != psize) 603 return NULL; 604 return (uint8_t *)prop; 605 606 } else { 607 return fdtdec_locate_byte_array(gd->fdt_blob, 608 ofnode_to_offset(node), propname, sz); 609 } 610 } 611 612 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, 613 const char *propname, struct fdt_pci_addr *addr) 614 { 615 const fdt32_t *cell; 616 int len; 617 int ret = -ENOENT; 618 619 debug("%s: %s: ", __func__, propname); 620 621 /* 622 * If we follow the pci bus bindings strictly, we should check 623 * the value of the node's parent node's #address-cells and 624 * #size-cells. They need to be 3 and 2 accordingly. However, 625 * for simplicity we skip the check here. 626 */ 627 cell = ofnode_get_property(node, propname, &len); 628 if (!cell) 629 goto fail; 630 631 if ((len % FDT_PCI_REG_SIZE) == 0) { 632 int num = len / FDT_PCI_REG_SIZE; 633 int i; 634 635 for (i = 0; i < num; i++) { 636 debug("pci address #%d: %08lx %08lx %08lx\n", i, 637 (ulong)fdt32_to_cpu(cell[0]), 638 (ulong)fdt32_to_cpu(cell[1]), 639 (ulong)fdt32_to_cpu(cell[2])); 640 if ((fdt32_to_cpu(*cell) & type) == type) { 641 addr->phys_hi = fdt32_to_cpu(cell[0]); 642 addr->phys_mid = fdt32_to_cpu(cell[1]); 643 addr->phys_lo = fdt32_to_cpu(cell[1]); 644 break; 645 } else { 646 cell += (FDT_PCI_ADDR_CELLS + 647 FDT_PCI_SIZE_CELLS); 648 } 649 } 650 651 if (i == num) { 652 ret = -ENXIO; 653 goto fail; 654 } 655 656 return 0; 657 } else { 658 ret = -EINVAL; 659 } 660 661 fail: 662 debug("(not found)\n"); 663 return ret; 664 } 665 666 int ofnode_read_addr_cells(ofnode node) 667 { 668 if (ofnode_is_np(node)) 669 return of_n_addr_cells(ofnode_to_np(node)); 670 else /* NOTE: this call should walk up the parent stack */ 671 return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); 672 } 673 674 int ofnode_read_size_cells(ofnode node) 675 { 676 if (ofnode_is_np(node)) 677 return of_n_size_cells(ofnode_to_np(node)); 678 else /* NOTE: this call should walk up the parent stack */ 679 return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); 680 } 681 682 int ofnode_read_simple_addr_cells(ofnode node) 683 { 684 if (ofnode_is_np(node)) 685 return of_simple_addr_cells(ofnode_to_np(node)); 686 else 687 return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); 688 } 689 690 int ofnode_read_simple_size_cells(ofnode node) 691 { 692 if (ofnode_is_np(node)) 693 return of_simple_size_cells(ofnode_to_np(node)); 694 else 695 return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); 696 } 697 698 bool ofnode_pre_reloc(ofnode node) 699 { 700 if (ofnode_read_bool(node, "u-boot,dm-pre-reloc")) 701 return true; 702 703 #ifdef CONFIG_TPL_BUILD 704 if (ofnode_read_bool(node, "u-boot,dm-tpl")) 705 return true; 706 #elif defined(CONFIG_SPL_BUILD) 707 if (ofnode_read_bool(node, "u-boot,dm-spl")) 708 return true; 709 #else 710 /* 711 * In regular builds individual spl and tpl handling both 712 * count as handled pre-relocation for later second init. 713 */ 714 if (ofnode_read_bool(node, "u-boot,dm-spl") || 715 ofnode_read_bool(node, "u-boot,dm-tpl")) 716 return true; 717 #endif 718 719 return false; 720 } 721 722 int ofnode_read_resource(ofnode node, uint index, struct resource *res) 723 { 724 if (ofnode_is_np(node)) { 725 return of_address_to_resource(ofnode_to_np(node), index, res); 726 } else { 727 struct fdt_resource fres; 728 int ret; 729 730 ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node), 731 "reg", index, &fres); 732 if (ret < 0) 733 return -EINVAL; 734 memset(res, '\0', sizeof(*res)); 735 res->start = fres.start; 736 res->end = fres.end; 737 738 return 0; 739 } 740 } 741 742 int ofnode_read_resource_byname(ofnode node, const char *name, 743 struct resource *res) 744 { 745 int index; 746 747 index = ofnode_stringlist_search(node, "reg-names", name); 748 if (index < 0) 749 return index; 750 751 return ofnode_read_resource(node, index, res); 752 } 753 754 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr) 755 { 756 if (ofnode_is_np(node)) 757 return of_translate_address(ofnode_to_np(node), in_addr); 758 else 759 return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr); 760 } 761