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 ofnode ofnode_first_subnode(ofnode node) 164 { 165 assert(ofnode_valid(node)); 166 if (ofnode_is_np(node)) 167 return np_to_ofnode(node.np->child); 168 169 return offset_to_ofnode( 170 fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node))); 171 } 172 173 ofnode ofnode_next_subnode(ofnode node) 174 { 175 assert(ofnode_valid(node)); 176 if (ofnode_is_np(node)) 177 return np_to_ofnode(node.np->sibling); 178 179 return offset_to_ofnode( 180 fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node))); 181 } 182 183 ofnode ofnode_get_parent(ofnode node) 184 { 185 ofnode parent; 186 187 assert(ofnode_valid(node)); 188 if (ofnode_is_np(node)) 189 parent = np_to_ofnode(of_get_parent(ofnode_to_np(node))); 190 else 191 parent.of_offset = fdt_parent_offset(gd->fdt_blob, 192 ofnode_to_offset(node)); 193 194 return parent; 195 } 196 197 const char *ofnode_get_name(ofnode node) 198 { 199 if(!ofnode_valid(node)){ 200 debug("%s node not valid\n", __func__); 201 return NULL; 202 } 203 if (ofnode_is_np(node)) 204 return strrchr(node.np->full_name, '/') + 1; 205 206 return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL); 207 } 208 209 ofnode ofnode_get_by_phandle(uint phandle) 210 { 211 ofnode node; 212 213 if (of_live_active()) 214 node = np_to_ofnode(of_find_node_by_phandle(phandle)); 215 else 216 node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob, 217 phandle); 218 219 return node; 220 } 221 222 int ofnode_read_size(ofnode node, const char *propname) 223 { 224 int len; 225 226 if (ofnode_is_np(node)) { 227 struct property *prop = of_find_property( 228 ofnode_to_np(node), propname, NULL); 229 230 if (prop) 231 return prop->length; 232 } else { 233 if (fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, 234 &len)) 235 return len; 236 } 237 238 return -EINVAL; 239 } 240 241 fdt_addr_t ofnode_get_addr_index(ofnode node, int index) 242 { 243 if (ofnode_is_np(node)) { 244 const __be32 *prop_val; 245 uint flags; 246 u64 size; 247 int na; 248 249 prop_val = of_get_address(ofnode_to_np(node), index, &size, 250 &flags); 251 if (!prop_val) 252 return FDT_ADDR_T_NONE; 253 na = of_n_addr_cells(ofnode_to_np(node)); 254 return of_read_number(prop_val, na); 255 } else { 256 return fdt_get_base_address(gd->fdt_blob, 257 ofnode_to_offset(node)); 258 } 259 260 return FDT_ADDR_T_NONE; 261 } 262 263 fdt_addr_t ofnode_get_addr(ofnode node) 264 { 265 return ofnode_get_addr_index(node, 0); 266 } 267 268 int ofnode_stringlist_search(ofnode node, const char *property, 269 const char *string) 270 { 271 if (ofnode_is_np(node)) { 272 return of_property_match_string(ofnode_to_np(node), 273 property, string); 274 } else { 275 int ret; 276 277 ret = fdt_stringlist_search(gd->fdt_blob, 278 ofnode_to_offset(node), property, 279 string); 280 if (ret == -FDT_ERR_NOTFOUND) 281 return -ENODATA; 282 else if (ret < 0) 283 return -EINVAL; 284 285 return ret; 286 } 287 } 288 289 int ofnode_read_string_index(ofnode node, const char *property, int index, 290 const char **outp) 291 { 292 if (ofnode_is_np(node)) { 293 return of_property_read_string_index(ofnode_to_np(node), 294 property, index, outp); 295 } else { 296 int len; 297 298 *outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node), 299 property, index, &len); 300 if (len < 0) 301 return -EINVAL; 302 return 0; 303 } 304 } 305 306 int ofnode_read_string_count(ofnode node, const char *property) 307 { 308 if (ofnode_is_np(node)) { 309 return of_property_count_strings(ofnode_to_np(node), property); 310 } else { 311 return fdt_stringlist_count(gd->fdt_blob, 312 ofnode_to_offset(node), property); 313 } 314 } 315 316 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in, 317 struct ofnode_phandle_args *out) 318 { 319 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 320 out->node = offset_to_ofnode(in->node); 321 out->args_count = in->args_count; 322 memcpy(out->args, in->args, sizeof(out->args)); 323 } 324 325 static void ofnode_from_of_phandle_args(struct of_phandle_args *in, 326 struct ofnode_phandle_args *out) 327 { 328 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 329 out->node = np_to_ofnode(in->np); 330 out->args_count = in->args_count; 331 memcpy(out->args, in->args, sizeof(out->args)); 332 } 333 334 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, 335 const char *cells_name, int cell_count, 336 int index, 337 struct ofnode_phandle_args *out_args) 338 { 339 if (ofnode_is_np(node)) { 340 struct of_phandle_args args; 341 int ret; 342 343 ret = of_parse_phandle_with_args(ofnode_to_np(node), 344 list_name, cells_name, index, &args); 345 if (ret) 346 return ret; 347 ofnode_from_of_phandle_args(&args, out_args); 348 } else { 349 struct fdtdec_phandle_args args; 350 int ret; 351 352 ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, 353 ofnode_to_offset(node), list_name, cells_name, 354 cell_count, index, &args); 355 if (ret) 356 return ret; 357 ofnode_from_fdtdec_phandle_args(&args, out_args); 358 } 359 360 return 0; 361 } 362 363 int ofnode_count_phandle_with_args(ofnode node, const char *list_name, 364 const char *cells_name) 365 { 366 if (ofnode_is_np(node)) 367 return of_count_phandle_with_args(ofnode_to_np(node), 368 list_name, cells_name); 369 else 370 return fdtdec_parse_phandle_with_args(gd->fdt_blob, 371 ofnode_to_offset(node), list_name, cells_name, 372 0, -1, NULL); 373 } 374 375 ofnode ofnode_path(const char *path) 376 { 377 if (of_live_active()) 378 return np_to_ofnode(of_find_node_by_path(path)); 379 else 380 return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path)); 381 } 382 383 const char *ofnode_get_chosen_prop(const char *name) 384 { 385 ofnode chosen_node; 386 387 chosen_node = ofnode_path("/chosen"); 388 389 return ofnode_read_string(chosen_node, name); 390 } 391 392 ofnode ofnode_get_chosen_node(const char *name) 393 { 394 const char *prop; 395 396 prop = ofnode_get_chosen_prop(name); 397 if (!prop) 398 return ofnode_null(); 399 400 return ofnode_path(prop); 401 } 402 403 static int decode_timing_property(ofnode node, const char *name, 404 struct timing_entry *result) 405 { 406 int length, ret = 0; 407 408 length = ofnode_read_size(node, name); 409 if (length < 0) { 410 debug("%s: could not find property %s\n", 411 ofnode_get_name(node), name); 412 return length; 413 } 414 415 if (length == sizeof(u32)) { 416 result->typ = ofnode_read_u32_default(node, name, 0); 417 result->min = result->typ; 418 result->max = result->typ; 419 } else { 420 ret = ofnode_read_u32_array(node, name, &result->min, 3); 421 } 422 423 return ret; 424 } 425 426 int ofnode_decode_display_timing(ofnode parent, int index, 427 struct display_timing *dt) 428 { 429 int i; 430 ofnode timings, node; 431 u32 val = 0; 432 int ret = 0; 433 434 timings = ofnode_find_subnode(parent, "display-timings"); 435 if (!ofnode_valid(timings)) 436 return -EINVAL; 437 438 i = 0; 439 ofnode_for_each_subnode(node, timings) { 440 if (i++ == index) 441 break; 442 } 443 444 if (!ofnode_valid(node)) 445 return -EINVAL; 446 447 memset(dt, 0, sizeof(*dt)); 448 449 ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch); 450 ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch); 451 ret |= decode_timing_property(node, "hactive", &dt->hactive); 452 ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len); 453 ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch); 454 ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch); 455 ret |= decode_timing_property(node, "vactive", &dt->vactive); 456 ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len); 457 ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock); 458 459 dt->flags = 0; 460 val = ofnode_read_u32_default(node, "vsync-active", -1); 461 if (val != -1) { 462 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : 463 DISPLAY_FLAGS_VSYNC_LOW; 464 } 465 val = ofnode_read_u32_default(node, "hsync-active", -1); 466 if (val != -1) { 467 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : 468 DISPLAY_FLAGS_HSYNC_LOW; 469 } 470 val = ofnode_read_u32_default(node, "de-active", -1); 471 if (val != -1) { 472 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : 473 DISPLAY_FLAGS_DE_LOW; 474 } 475 val = ofnode_read_u32_default(node, "pixelclk-active", -1); 476 if (val != -1) { 477 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : 478 DISPLAY_FLAGS_PIXDATA_NEGEDGE; 479 } 480 481 if (ofnode_read_bool(node, "interlaced")) 482 dt->flags |= DISPLAY_FLAGS_INTERLACED; 483 if (ofnode_read_bool(node, "doublescan")) 484 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; 485 if (ofnode_read_bool(node, "doubleclk")) 486 dt->flags |= DISPLAY_FLAGS_DOUBLECLK; 487 488 return ret; 489 } 490 491 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp) 492 { 493 if (ofnode_is_np(node)) 494 return of_get_property(ofnode_to_np(node), propname, lenp); 495 else 496 return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), 497 propname, lenp); 498 } 499 500 bool ofnode_is_available(ofnode node) 501 { 502 if (ofnode_is_np(node)) 503 return of_device_is_available(ofnode_to_np(node)); 504 else 505 return fdtdec_get_is_enabled(gd->fdt_blob, 506 ofnode_to_offset(node)); 507 } 508 509 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, 510 fdt_size_t *sizep) 511 { 512 if (ofnode_is_np(node)) { 513 int na, ns; 514 int psize; 515 const struct device_node *np = ofnode_to_np(node); 516 const __be32 *prop = of_get_property(np, property, &psize); 517 518 if (!prop) 519 return FDT_ADDR_T_NONE; 520 na = of_n_addr_cells(np); 521 ns = of_n_addr_cells(np); 522 *sizep = of_read_number(prop + na, ns); 523 return of_read_number(prop, na); 524 } else { 525 return fdtdec_get_addr_size(gd->fdt_blob, 526 ofnode_to_offset(node), property, 527 sizep); 528 } 529 } 530 531 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, 532 size_t sz) 533 { 534 if (ofnode_is_np(node)) { 535 const struct device_node *np = ofnode_to_np(node); 536 int psize; 537 const __be32 *prop = of_get_property(np, propname, &psize); 538 539 if (!prop || sz != psize) 540 return NULL; 541 return (uint8_t *)prop; 542 543 } else { 544 return fdtdec_locate_byte_array(gd->fdt_blob, 545 ofnode_to_offset(node), propname, sz); 546 } 547 } 548 549 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, 550 const char *propname, struct fdt_pci_addr *addr) 551 { 552 const fdt32_t *cell; 553 int len; 554 int ret = -ENOENT; 555 556 debug("%s: %s: ", __func__, propname); 557 558 /* 559 * If we follow the pci bus bindings strictly, we should check 560 * the value of the node's parent node's #address-cells and 561 * #size-cells. They need to be 3 and 2 accordingly. However, 562 * for simplicity we skip the check here. 563 */ 564 cell = ofnode_get_property(node, propname, &len); 565 if (!cell) 566 goto fail; 567 568 if ((len % FDT_PCI_REG_SIZE) == 0) { 569 int num = len / FDT_PCI_REG_SIZE; 570 int i; 571 572 for (i = 0; i < num; i++) { 573 debug("pci address #%d: %08lx %08lx %08lx\n", i, 574 (ulong)fdt32_to_cpu(cell[0]), 575 (ulong)fdt32_to_cpu(cell[1]), 576 (ulong)fdt32_to_cpu(cell[2])); 577 if ((fdt32_to_cpu(*cell) & type) == type) { 578 addr->phys_hi = fdt32_to_cpu(cell[0]); 579 addr->phys_mid = fdt32_to_cpu(cell[1]); 580 addr->phys_lo = fdt32_to_cpu(cell[1]); 581 break; 582 } else { 583 cell += (FDT_PCI_ADDR_CELLS + 584 FDT_PCI_SIZE_CELLS); 585 } 586 } 587 588 if (i == num) { 589 ret = -ENXIO; 590 goto fail; 591 } 592 593 return 0; 594 } else { 595 ret = -EINVAL; 596 } 597 598 fail: 599 debug("(not found)\n"); 600 return ret; 601 } 602 603 int ofnode_read_addr_cells(ofnode node) 604 { 605 if (ofnode_is_np(node)) 606 return of_n_addr_cells(ofnode_to_np(node)); 607 else /* NOTE: this call should walk up the parent stack */ 608 return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); 609 } 610 611 int ofnode_read_size_cells(ofnode node) 612 { 613 if (ofnode_is_np(node)) 614 return of_n_size_cells(ofnode_to_np(node)); 615 else /* NOTE: this call should walk up the parent stack */ 616 return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); 617 } 618 619 int ofnode_read_simple_addr_cells(ofnode node) 620 { 621 if (ofnode_is_np(node)) 622 return of_simple_addr_cells(ofnode_to_np(node)); 623 else 624 return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); 625 } 626 627 int ofnode_read_simple_size_cells(ofnode node) 628 { 629 if (ofnode_is_np(node)) 630 return of_simple_size_cells(ofnode_to_np(node)); 631 else 632 return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); 633 } 634 635 bool ofnode_pre_reloc(ofnode node) 636 { 637 if (ofnode_read_bool(node, "u-boot,dm-pre-reloc")) 638 return true; 639 640 #ifdef CONFIG_TPL_BUILD 641 if (ofnode_read_bool(node, "u-boot,dm-tpl")) 642 return true; 643 #elif defined(CONFIG_SPL_BUILD) 644 if (ofnode_read_bool(node, "u-boot,dm-spl")) 645 return true; 646 #else 647 /* 648 * In regular builds individual spl and tpl handling both 649 * count as handled pre-relocation for later second init. 650 */ 651 if (ofnode_read_bool(node, "u-boot,dm-spl") || 652 ofnode_read_bool(node, "u-boot,dm-tpl")) 653 return true; 654 #endif 655 656 return false; 657 } 658 659 int ofnode_read_resource(ofnode node, uint index, struct resource *res) 660 { 661 if (ofnode_is_np(node)) { 662 return of_address_to_resource(ofnode_to_np(node), index, res); 663 } else { 664 struct fdt_resource fres; 665 int ret; 666 667 ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node), 668 "reg", index, &fres); 669 if (ret < 0) 670 return -EINVAL; 671 memset(res, '\0', sizeof(*res)); 672 res->start = fres.start; 673 res->end = fres.end; 674 675 return 0; 676 } 677 } 678 679 int ofnode_read_resource_byname(ofnode node, const char *name, 680 struct resource *res) 681 { 682 int index; 683 684 index = ofnode_stringlist_search(node, "reg-names", name); 685 if (index < 0) 686 return index; 687 688 return ofnode_read_resource(node, index, res); 689 } 690