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