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