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