1 /* 2 * (C) Copyright 2007 3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com 4 * 5 * Copyright 2010-2011 Freescale Semiconductor, Inc. 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 11 #include <android_image.h> 12 #include <exports.h> 13 #include <fdt_support.h> 14 #include <fdtdec.h> 15 #include <inttypes.h> 16 #include <malloc.h> 17 #ifdef CONFIG_MTD_BLK 18 #include <mtd_blk.h> 19 #endif 20 #include <stdio_dev.h> 21 #include <asm/arch/hotkey.h> 22 #include <asm/global_data.h> 23 #include <linux/ctype.h> 24 #include <linux/libfdt.h> 25 #include <linux/types.h> 26 27 DECLARE_GLOBAL_DATA_PTR; 28 29 /** 30 * fdt_getprop_u32_default_node - Return a node's property or a default 31 * 32 * @fdt: ptr to device tree 33 * @off: offset of node 34 * @cell: cell offset in property 35 * @prop: property name 36 * @dflt: default value if the property isn't found 37 * 38 * Convenience function to return a node's property or a default value if 39 * the property doesn't exist. 40 */ 41 u32 fdt_getprop_u32_default_node(const void *fdt, int off, int cell, 42 const char *prop, const u32 dflt) 43 { 44 const fdt32_t *val; 45 int len; 46 47 val = fdt_getprop(fdt, off, prop, &len); 48 49 /* Check if property exists */ 50 if (!val) 51 return dflt; 52 53 /* Check if property is long enough */ 54 if (len < ((cell + 1) * sizeof(uint32_t))) 55 return dflt; 56 57 return fdt32_to_cpu(*val); 58 } 59 60 /** 61 * fdt_getprop_u32_default - Find a node and return it's property or a default 62 * 63 * @fdt: ptr to device tree 64 * @path: path of node 65 * @prop: property name 66 * @dflt: default value if the property isn't found 67 * 68 * Convenience function to find a node and return it's property or a 69 * default value if it doesn't exist. 70 */ 71 u32 fdt_getprop_u32_default(const void *fdt, const char *path, 72 const char *prop, const u32 dflt) 73 { 74 int off; 75 76 off = fdt_path_offset(fdt, path); 77 if (off < 0) 78 return dflt; 79 80 return fdt_getprop_u32_default_node(fdt, off, 0, prop, dflt); 81 } 82 83 /** 84 * fdt_find_and_setprop: Find a node and set it's property 85 * 86 * @fdt: ptr to device tree 87 * @node: path of node 88 * @prop: property name 89 * @val: ptr to new value 90 * @len: length of new property value 91 * @create: flag to create the property if it doesn't exist 92 * 93 * Convenience function to directly set a property given the path to the node. 94 */ 95 int fdt_find_and_setprop(void *fdt, const char *node, const char *prop, 96 const void *val, int len, int create) 97 { 98 int nodeoff = fdt_path_offset(fdt, node); 99 100 if (nodeoff < 0) 101 return nodeoff; 102 103 if ((!create) && (fdt_get_property(fdt, nodeoff, prop, NULL) == NULL)) 104 return 0; /* create flag not set; so exit quietly */ 105 106 return fdt_setprop(fdt, nodeoff, prop, val, len); 107 } 108 109 /** 110 * fdt_find_or_add_subnode() - find or possibly add a subnode of a given node 111 * 112 * @fdt: pointer to the device tree blob 113 * @parentoffset: structure block offset of a node 114 * @name: name of the subnode to locate 115 * 116 * fdt_subnode_offset() finds a subnode of the node with a given name. 117 * If the subnode does not exist, it will be created. 118 */ 119 int fdt_find_or_add_subnode(void *fdt, int parentoffset, const char *name) 120 { 121 int offset; 122 123 offset = fdt_subnode_offset(fdt, parentoffset, name); 124 125 if (offset == -FDT_ERR_NOTFOUND) 126 offset = fdt_add_subnode(fdt, parentoffset, name); 127 128 if (offset < 0) 129 printf("%s: %s: %s\n", __func__, name, fdt_strerror(offset)); 130 131 return offset; 132 } 133 134 /* rename to CONFIG_OF_STDOUT_PATH ? */ 135 #if defined(OF_STDOUT_PATH) 136 static int fdt_fixup_stdout(void *fdt, int chosenoff) 137 { 138 return fdt_setprop(fdt, chosenoff, "linux,stdout-path", 139 OF_STDOUT_PATH, strlen(OF_STDOUT_PATH) + 1); 140 } 141 #elif defined(CONFIG_OF_STDOUT_VIA_ALIAS) && defined(CONFIG_CONS_INDEX) 142 static int fdt_fixup_stdout(void *fdt, int chosenoff) 143 { 144 int err; 145 int aliasoff; 146 char sername[9] = { 0 }; 147 const void *path; 148 int len; 149 char tmp[256]; /* long enough */ 150 151 sprintf(sername, "serial%d", CONFIG_CONS_INDEX - 1); 152 153 aliasoff = fdt_path_offset(fdt, "/aliases"); 154 if (aliasoff < 0) { 155 err = aliasoff; 156 goto noalias; 157 } 158 159 path = fdt_getprop(fdt, aliasoff, sername, &len); 160 if (!path) { 161 err = len; 162 goto noalias; 163 } 164 165 /* fdt_setprop may break "path" so we copy it to tmp buffer */ 166 memcpy(tmp, path, len); 167 168 err = fdt_setprop(fdt, chosenoff, "linux,stdout-path", tmp, len); 169 if (err < 0) 170 printf("WARNING: could not set linux,stdout-path %s.\n", 171 fdt_strerror(err)); 172 173 return err; 174 175 noalias: 176 printf("WARNING: %s: could not read %s alias: %s\n", 177 __func__, sername, fdt_strerror(err)); 178 179 return 0; 180 } 181 #else 182 static int fdt_fixup_stdout(void *fdt, int chosenoff) 183 { 184 return 0; 185 } 186 #endif 187 188 static inline int fdt_setprop_uxx(void *fdt, int nodeoffset, const char *name, 189 uint64_t val, int is_u64) 190 { 191 if (is_u64) 192 return fdt_setprop_u64(fdt, nodeoffset, name, val); 193 else 194 return fdt_setprop_u32(fdt, nodeoffset, name, (uint32_t)val); 195 } 196 197 int fdt_root(void *fdt) 198 { 199 char *serial; 200 int err; 201 202 err = fdt_check_header(fdt); 203 if (err < 0) { 204 printf("fdt_root: %s\n", fdt_strerror(err)); 205 return err; 206 } 207 208 serial = env_get("serial#"); 209 if (serial) { 210 err = fdt_setprop(fdt, 0, "serial-number", serial, 211 strlen(serial) + 1); 212 213 if (err < 0) { 214 printf("WARNING: could not set serial-number %s.\n", 215 fdt_strerror(err)); 216 return err; 217 } 218 } 219 220 return 0; 221 } 222 223 int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end) 224 { 225 int nodeoffset; 226 int err, j, total; 227 int is_u64; 228 uint64_t addr, size; 229 230 /* just return if the size of initrd is zero */ 231 if (initrd_start == initrd_end) 232 return 0; 233 234 /* find or create "/chosen" node. */ 235 nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); 236 if (nodeoffset < 0) 237 return nodeoffset; 238 239 total = fdt_num_mem_rsv(fdt); 240 241 /* 242 * Look for an existing entry and update it. If we don't find 243 * the entry, we will j be the next available slot. 244 */ 245 for (j = 0; j < total; j++) { 246 err = fdt_get_mem_rsv(fdt, j, &addr, &size); 247 if (addr == initrd_start) { 248 fdt_del_mem_rsv(fdt, j); 249 break; 250 } 251 } 252 253 err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start); 254 if (err < 0) { 255 printf("fdt_initrd: %s\n", fdt_strerror(err)); 256 return err; 257 } 258 259 is_u64 = (fdt_address_cells(fdt, 0) == 2); 260 261 err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-start", 262 (uint64_t)initrd_start, is_u64); 263 264 if (err < 0) { 265 printf("WARNING: could not set linux,initrd-start %s.\n", 266 fdt_strerror(err)); 267 return err; 268 } 269 270 err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-end", 271 (uint64_t)initrd_end, is_u64); 272 273 if (err < 0) { 274 printf("WARNING: could not set linux,initrd-end %s.\n", 275 fdt_strerror(err)); 276 277 return err; 278 } 279 280 return 0; 281 } 282 283 int fdt_bootargs_append(void *fdt, char *data) 284 { 285 const char *arr_bootargs[] = { "bootargs", "bootargs_ext" }; 286 int nodeoffset, len; 287 const char *bootargs; 288 char *str; 289 int i, ret = 0; 290 291 if (!data) 292 return 0; 293 294 /* find or create "/chosen" node. */ 295 nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); 296 if (nodeoffset < 0) 297 return nodeoffset; 298 299 for (i = 0; i < ARRAY_SIZE(arr_bootargs); i++) { 300 bootargs = fdt_getprop(fdt, nodeoffset, 301 arr_bootargs[i], NULL); 302 if (bootargs) { 303 len = strlen(bootargs) + strlen(data) + 2; 304 str = malloc(len); 305 if (!str) 306 return -ENOMEM; 307 308 fdt_increase_size(fdt, 512); 309 snprintf(str, len, "%s %s", bootargs, data); 310 ret = fdt_setprop(fdt, nodeoffset, arr_bootargs[i], 311 str, len); 312 if (ret < 0) 313 printf("WARNING: could not set bootargs %s.\n", fdt_strerror(ret)); 314 315 free(str); 316 break; 317 } 318 } 319 320 return ret; 321 } 322 323 int fdt_bootargs_append_ab(void *fdt, char *slot) 324 { 325 char *str; 326 int len, ret = 0; 327 328 if (!slot) 329 return 0; 330 331 len = strlen(ANDROID_ARG_SLOT_SUFFIX) + strlen(slot) + 1; 332 str = malloc(len); 333 if (!str) 334 return -ENOMEM; 335 336 snprintf(str, len, "%s%s", ANDROID_ARG_SLOT_SUFFIX, slot); 337 ret = fdt_bootargs_append(fdt, str); 338 if (ret) 339 printf("Apend slot info to bootargs fail"); 340 341 free(str); 342 343 return ret; 344 } 345 346 int fdt_chosen(void *fdt) 347 { 348 /* 349 * "bootargs_ext" is used when dtbo is applied. 350 */ 351 const char *arr_bootargs[] = { "bootargs", "bootargs_ext" }; 352 int nodeoffset; 353 int err; 354 int i; 355 char *str; /* used to set string properties */ 356 int dump; 357 358 dump = is_hotkey(HK_CMDLINE); 359 360 err = fdt_check_header(fdt); 361 if (err < 0) { 362 printf("fdt_chosen: %s\n", fdt_strerror(err)); 363 return err; 364 } 365 366 /* find or create "/chosen" node. */ 367 nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); 368 if (nodeoffset < 0) 369 return nodeoffset; 370 371 str = env_get("bootargs"); 372 if (str) { 373 #ifdef CONFIG_ARCH_ROCKCHIP 374 const char *bootargs; 375 376 if (dump) 377 printf("## U-Boot bootargs: %s\n", str); 378 379 for (i = 0; i < ARRAY_SIZE(arr_bootargs); i++) { 380 bootargs = fdt_getprop(fdt, nodeoffset, 381 arr_bootargs[i], NULL); 382 if (bootargs) { 383 if (dump) 384 printf("## Kernel %s: %s\n", 385 arr_bootargs[i], bootargs); 386 /* 387 * Append kernel bootargs 388 * If use AB system, delete default "root=" which route 389 * to rootfs. Then the ab bootctl will choose the 390 * high priority system to boot and add its UUID 391 * to cmdline. The format is "roo=PARTUUID=xxxx...". 392 */ 393 hotkey_run(HK_INITCALL); 394 #ifdef CONFIG_ANDROID_AB 395 env_update_filter("bootargs", bootargs, "root="); 396 #else 397 env_update("bootargs", bootargs); 398 #endif 399 #ifdef CONFIG_MTD_BLK 400 char *mtd_par_info = mtd_part_parse(NULL); 401 402 if (mtd_par_info) { 403 if (memcmp(env_get("devtype"), "mtd", 3) == 0) 404 env_update("bootargs", mtd_par_info); 405 } 406 #endif 407 /* 408 * Initrd fixup: remove unused "initrd=0x...,0x...", 409 * this for compatible with legacy parameter.txt 410 */ 411 env_delete("bootargs", "initrd=", 0); 412 413 /* 414 * If uart is required to be disabled during 415 * power on, it would be not initialized by 416 * any pre-loader and U-Boot. 417 * 418 * If we don't remove earlycon from commandline, 419 * kernel hangs while using earlycon to putc/getc 420 * which may dead loop for waiting uart status. 421 * (It seems the root cause is baundrate is not 422 * initilalized) 423 * 424 * So let's remove earlycon from commandline. 425 */ 426 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 427 env_delete("bootargs", "earlycon=", 0); 428 } 429 #endif 430 } 431 432 str = env_get("bootargs"); 433 err = fdt_setprop(fdt, nodeoffset, "bootargs", str, 434 strlen(str) + 1); 435 if (err < 0) { 436 printf("WARNING: could not set bootargs %s.\n", 437 fdt_strerror(err)); 438 return err; 439 } 440 } 441 442 if (dump) 443 printf("## Merged bootargs: %s\n", env_get("bootargs")); 444 445 return fdt_fixup_stdout(fdt, nodeoffset); 446 } 447 448 void do_fixup_by_path(void *fdt, const char *path, const char *prop, 449 const void *val, int len, int create) 450 { 451 #if defined(DEBUG) 452 int i; 453 debug("Updating property '%s/%s' = ", path, prop); 454 for (i = 0; i < len; i++) 455 debug(" %.2x", *(u8*)(val+i)); 456 debug("\n"); 457 #endif 458 int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create); 459 if (rc) 460 printf("Unable to update property %s:%s, err=%s\n", 461 path, prop, fdt_strerror(rc)); 462 } 463 464 void do_fixup_by_path_u32(void *fdt, const char *path, const char *prop, 465 u32 val, int create) 466 { 467 fdt32_t tmp = cpu_to_fdt32(val); 468 do_fixup_by_path(fdt, path, prop, &tmp, sizeof(tmp), create); 469 } 470 471 void do_fixup_by_prop(void *fdt, 472 const char *pname, const void *pval, int plen, 473 const char *prop, const void *val, int len, 474 int create) 475 { 476 int off; 477 #if defined(DEBUG) 478 int i; 479 debug("Updating property '%s' = ", prop); 480 for (i = 0; i < len; i++) 481 debug(" %.2x", *(u8*)(val+i)); 482 debug("\n"); 483 #endif 484 off = fdt_node_offset_by_prop_value(fdt, -1, pname, pval, plen); 485 while (off != -FDT_ERR_NOTFOUND) { 486 if (create || (fdt_get_property(fdt, off, prop, NULL) != NULL)) 487 fdt_setprop(fdt, off, prop, val, len); 488 off = fdt_node_offset_by_prop_value(fdt, off, pname, pval, plen); 489 } 490 } 491 492 void do_fixup_by_prop_u32(void *fdt, 493 const char *pname, const void *pval, int plen, 494 const char *prop, u32 val, int create) 495 { 496 fdt32_t tmp = cpu_to_fdt32(val); 497 do_fixup_by_prop(fdt, pname, pval, plen, prop, &tmp, 4, create); 498 } 499 500 void do_fixup_by_compat(void *fdt, const char *compat, 501 const char *prop, const void *val, int len, int create) 502 { 503 int off = -1; 504 #if defined(DEBUG) 505 int i; 506 debug("Updating property '%s' = ", prop); 507 for (i = 0; i < len; i++) 508 debug(" %.2x", *(u8*)(val+i)); 509 debug("\n"); 510 #endif 511 off = fdt_node_offset_by_compatible(fdt, -1, compat); 512 while (off != -FDT_ERR_NOTFOUND) { 513 if (create || (fdt_get_property(fdt, off, prop, NULL) != NULL)) 514 fdt_setprop(fdt, off, prop, val, len); 515 off = fdt_node_offset_by_compatible(fdt, off, compat); 516 } 517 } 518 519 void do_fixup_by_compat_u32(void *fdt, const char *compat, 520 const char *prop, u32 val, int create) 521 { 522 fdt32_t tmp = cpu_to_fdt32(val); 523 do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create); 524 } 525 526 #ifdef CONFIG_ARCH_FIXUP_FDT_MEMORY 527 /* 528 * fdt_pack_reg - pack address and size array into the "reg"-suitable stream 529 */ 530 static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size, 531 int n) 532 { 533 int i; 534 int address_cells = fdt_address_cells(fdt, 0); 535 int size_cells = fdt_size_cells(fdt, 0); 536 char *p = buf; 537 538 for (i = 0; i < n; i++) { 539 if (address_cells == 2) 540 *(fdt64_t *)p = cpu_to_fdt64(address[i]); 541 else 542 *(fdt32_t *)p = cpu_to_fdt32(address[i]); 543 p += 4 * address_cells; 544 545 if (size_cells == 2) 546 *(fdt64_t *)p = cpu_to_fdt64(size[i]); 547 else 548 *(fdt32_t *)p = cpu_to_fdt32(size[i]); 549 p += 4 * size_cells; 550 } 551 552 return p - (char *)buf; 553 } 554 555 int fdt_record_loadable(void *blob, u32 index, const char *name, 556 uintptr_t load_addr, u32 size, uintptr_t entry_point, 557 const char *type, const char *os) 558 { 559 int err, node; 560 561 err = fdt_check_header(blob); 562 if (err < 0) { 563 printf("%s: %s\n", __func__, fdt_strerror(err)); 564 return err; 565 } 566 567 /* find or create "/fit-images" node */ 568 node = fdt_find_or_add_subnode(blob, 0, "fit-images"); 569 if (node < 0) 570 return node; 571 572 /* find or create "/fit-images/<name>" node */ 573 node = fdt_find_or_add_subnode(blob, node, name); 574 if (node < 0) 575 return node; 576 577 /* 578 * We record these as 32bit entities, possibly truncating addresses. 579 * However, spl_fit.c is not 64bit safe either: i.e. we should not 580 * have an issue here. 581 */ 582 fdt_setprop_u32(blob, node, "load-addr", load_addr); 583 if (entry_point != -1) 584 fdt_setprop_u32(blob, node, "entry-point", entry_point); 585 fdt_setprop_u32(blob, node, "size", size); 586 if (type) 587 fdt_setprop_string(blob, node, "type", type); 588 if (os) 589 fdt_setprop_string(blob, node, "os", os); 590 591 return node; 592 } 593 594 #ifdef CONFIG_NR_DRAM_BANKS 595 #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS 596 #else 597 #define MEMORY_BANKS_MAX 4 598 #endif 599 int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks) 600 { 601 int err, nodeoffset; 602 int len; 603 u8 tmp[MEMORY_BANKS_MAX * 16]; /* Up to 64-bit address + 64-bit size */ 604 605 if (banks > MEMORY_BANKS_MAX) { 606 printf("%s: num banks %d exceeds hardcoded limit %d." 607 " Recompile with higher MEMORY_BANKS_MAX?\n", 608 __FUNCTION__, banks, MEMORY_BANKS_MAX); 609 return -1; 610 } 611 612 err = fdt_check_header(blob); 613 if (err < 0) { 614 printf("%s: %s\n", __FUNCTION__, fdt_strerror(err)); 615 return err; 616 } 617 618 /* find or create "/memory" node. */ 619 nodeoffset = fdt_find_or_add_subnode(blob, 0, "memory"); 620 if (nodeoffset < 0) 621 return nodeoffset; 622 623 err = fdt_setprop(blob, nodeoffset, "device_type", "memory", 624 sizeof("memory")); 625 if (err < 0) { 626 printf("WARNING: could not set %s %s.\n", "device_type", 627 fdt_strerror(err)); 628 return err; 629 } 630 631 if (!banks) 632 return 0; 633 634 len = fdt_pack_reg(blob, tmp, start, size, banks); 635 636 err = fdt_setprop(blob, nodeoffset, "reg", tmp, len); 637 if (err < 0) { 638 printf("WARNING: could not set %s %s.\n", 639 "reg", fdt_strerror(err)); 640 return err; 641 } 642 return 0; 643 } 644 645 int fdt_fixup_memory(void *blob, u64 start, u64 size) 646 { 647 return fdt_fixup_memory_banks(blob, &start, &size, 1); 648 } 649 650 int fdt_update_reserved_memory(void *blob, char *name, u64 start, u64 size) 651 { 652 int nodeoffset, len, err; 653 u8 tmp[16]; /* Up to 64-bit address + 64-bit size */ 654 655 nodeoffset = fdt_node_offset_by_compatible(blob, 0, name); 656 if (nodeoffset < 0) 657 debug("Can't find nodeoffset: %d\n", nodeoffset); 658 659 if (!size) 660 return nodeoffset; 661 662 len = fdt_pack_reg(blob, tmp, &start, &size, 1); 663 err = fdt_setprop(blob, nodeoffset, "reg", tmp, len); 664 if (err < 0) { 665 printf("WARNING: could not set %s %s.\n", 666 "reg", fdt_strerror(err)); 667 return err; 668 } 669 670 return nodeoffset; 671 } 672 #endif 673 674 void fdt_fixup_ethernet(void *fdt) 675 { 676 int i = 0, j, prop; 677 char *tmp, *end; 678 char mac[16]; 679 const char *path; 680 unsigned char mac_addr[ARP_HLEN]; 681 int offset; 682 #ifdef FDT_SEQ_MACADDR_FROM_ENV 683 int nodeoff; 684 const struct fdt_property *fdt_prop; 685 #endif 686 687 if (fdt_path_offset(fdt, "/aliases") < 0) 688 return; 689 690 /* Cycle through all aliases */ 691 for (prop = 0; ; prop++) { 692 const char *name; 693 694 /* FDT might have been edited, recompute the offset */ 695 offset = fdt_first_property_offset(fdt, 696 fdt_path_offset(fdt, "/aliases")); 697 /* Select property number 'prop' */ 698 for (j = 0; j < prop; j++) 699 offset = fdt_next_property_offset(fdt, offset); 700 701 if (offset < 0) 702 break; 703 704 path = fdt_getprop_by_offset(fdt, offset, &name, NULL); 705 if (!strncmp(name, "ethernet", 8)) { 706 /* Treat plain "ethernet" same as "ethernet0". */ 707 if (!strcmp(name, "ethernet") 708 #ifdef FDT_SEQ_MACADDR_FROM_ENV 709 || !strcmp(name, "ethernet0") 710 #endif 711 ) 712 i = 0; 713 #ifndef FDT_SEQ_MACADDR_FROM_ENV 714 else 715 i = trailing_strtol(name); 716 #endif 717 if (i != -1) { 718 if (i == 0) 719 strcpy(mac, "ethaddr"); 720 else 721 sprintf(mac, "eth%daddr", i); 722 } else { 723 continue; 724 } 725 #ifdef FDT_SEQ_MACADDR_FROM_ENV 726 nodeoff = fdt_path_offset(fdt, path); 727 fdt_prop = fdt_get_property(fdt, nodeoff, "status", 728 NULL); 729 if (fdt_prop && !strcmp(fdt_prop->data, "disabled")) 730 continue; 731 i++; 732 #endif 733 tmp = env_get(mac); 734 if (!tmp) 735 continue; 736 737 for (j = 0; j < 6; j++) { 738 mac_addr[j] = tmp ? 739 simple_strtoul(tmp, &end, 16) : 0; 740 if (tmp) 741 tmp = (*end) ? end + 1 : end; 742 } 743 744 do_fixup_by_path(fdt, path, "mac-address", 745 &mac_addr, 6, 0); 746 do_fixup_by_path(fdt, path, "local-mac-address", 747 &mac_addr, 6, 1); 748 } 749 } 750 } 751 752 /* Resize the fdt to its actual size + a bit of padding */ 753 int fdt_shrink_to_minimum(void *blob, uint extrasize) 754 { 755 int i; 756 uint64_t addr, size; 757 int total, ret; 758 uint actualsize; 759 760 if (!blob) 761 return 0; 762 763 total = fdt_num_mem_rsv(blob); 764 for (i = 0; i < total; i++) { 765 fdt_get_mem_rsv(blob, i, &addr, &size); 766 if (addr == (uintptr_t)blob) { 767 fdt_del_mem_rsv(blob, i); 768 break; 769 } 770 } 771 772 /* 773 * Calculate the actual size of the fdt 774 * plus the size needed for 5 fdt_add_mem_rsv, one 775 * for the fdt itself and 4 for a possible initrd 776 * ((initrd-start + initrd-end) * 2 (name & value)) 777 */ 778 actualsize = fdt_off_dt_strings(blob) + 779 fdt_size_dt_strings(blob) + 5 * sizeof(struct fdt_reserve_entry); 780 781 actualsize += extrasize; 782 /* Make it so the fdt ends on a page boundary */ 783 actualsize = ALIGN(actualsize + ((uintptr_t)blob & 0xfff), 0x1000); 784 actualsize = actualsize - ((uintptr_t)blob & 0xfff); 785 786 /* Change the fdt header to reflect the correct size */ 787 fdt_set_totalsize(blob, actualsize); 788 789 /* Add the new reservation */ 790 ret = fdt_add_mem_rsv(blob, (uintptr_t)blob, actualsize); 791 if (ret < 0) 792 return ret; 793 794 return actualsize; 795 } 796 797 #ifdef CONFIG_PCI 798 #define CONFIG_SYS_PCI_NR_INBOUND_WIN 4 799 800 #define FDT_PCI_PREFETCH (0x40000000) 801 #define FDT_PCI_MEM32 (0x02000000) 802 #define FDT_PCI_IO (0x01000000) 803 #define FDT_PCI_MEM64 (0x03000000) 804 805 int fdt_pci_dma_ranges(void *blob, int phb_off, struct pci_controller *hose) { 806 807 int addrcell, sizecell, len, r; 808 u32 *dma_range; 809 /* sized based on pci addr cells, size-cells, & address-cells */ 810 u32 dma_ranges[(3 + 2 + 2) * CONFIG_SYS_PCI_NR_INBOUND_WIN]; 811 812 addrcell = fdt_getprop_u32_default(blob, "/", "#address-cells", 1); 813 sizecell = fdt_getprop_u32_default(blob, "/", "#size-cells", 1); 814 815 dma_range = &dma_ranges[0]; 816 for (r = 0; r < hose->region_count; r++) { 817 u64 bus_start, phys_start, size; 818 819 /* skip if !PCI_REGION_SYS_MEMORY */ 820 if (!(hose->regions[r].flags & PCI_REGION_SYS_MEMORY)) 821 continue; 822 823 bus_start = (u64)hose->regions[r].bus_start; 824 phys_start = (u64)hose->regions[r].phys_start; 825 size = (u64)hose->regions[r].size; 826 827 dma_range[0] = 0; 828 if (size >= 0x100000000ull) 829 dma_range[0] |= FDT_PCI_MEM64; 830 else 831 dma_range[0] |= FDT_PCI_MEM32; 832 if (hose->regions[r].flags & PCI_REGION_PREFETCH) 833 dma_range[0] |= FDT_PCI_PREFETCH; 834 #ifdef CONFIG_SYS_PCI_64BIT 835 dma_range[1] = bus_start >> 32; 836 #else 837 dma_range[1] = 0; 838 #endif 839 dma_range[2] = bus_start & 0xffffffff; 840 841 if (addrcell == 2) { 842 dma_range[3] = phys_start >> 32; 843 dma_range[4] = phys_start & 0xffffffff; 844 } else { 845 dma_range[3] = phys_start & 0xffffffff; 846 } 847 848 if (sizecell == 2) { 849 dma_range[3 + addrcell + 0] = size >> 32; 850 dma_range[3 + addrcell + 1] = size & 0xffffffff; 851 } else { 852 dma_range[3 + addrcell + 0] = size & 0xffffffff; 853 } 854 855 dma_range += (3 + addrcell + sizecell); 856 } 857 858 len = dma_range - &dma_ranges[0]; 859 if (len) 860 fdt_setprop(blob, phb_off, "dma-ranges", &dma_ranges[0], len*4); 861 862 return 0; 863 } 864 #endif 865 866 int fdt_increase_size(void *fdt, int add_len) 867 { 868 int newlen; 869 870 newlen = fdt_totalsize(fdt) + add_len; 871 872 /* Open in place with a new len */ 873 return fdt_open_into(fdt, fdt, newlen); 874 } 875 876 #ifdef CONFIG_FDT_FIXUP_PARTITIONS 877 #include <jffs2/load_kernel.h> 878 #include <mtd_node.h> 879 880 struct reg_cell { 881 unsigned int r0; 882 unsigned int r1; 883 }; 884 885 int fdt_del_subnodes(const void *blob, int parent_offset) 886 { 887 int off, ndepth; 888 int ret; 889 890 for (ndepth = 0, off = fdt_next_node(blob, parent_offset, &ndepth); 891 (off >= 0) && (ndepth > 0); 892 off = fdt_next_node(blob, off, &ndepth)) { 893 if (ndepth == 1) { 894 debug("delete %s: offset: %x\n", 895 fdt_get_name(blob, off, 0), off); 896 ret = fdt_del_node((void *)blob, off); 897 if (ret < 0) { 898 printf("Can't delete node: %s\n", 899 fdt_strerror(ret)); 900 return ret; 901 } else { 902 ndepth = 0; 903 off = parent_offset; 904 } 905 } 906 } 907 return 0; 908 } 909 910 int fdt_del_partitions(void *blob, int parent_offset) 911 { 912 const void *prop; 913 int ndepth = 0; 914 int off; 915 int ret; 916 917 off = fdt_next_node(blob, parent_offset, &ndepth); 918 if (off > 0 && ndepth == 1) { 919 prop = fdt_getprop(blob, off, "label", NULL); 920 if (prop == NULL) { 921 /* 922 * Could not find label property, nand {}; node? 923 * Check subnode, delete partitions there if any. 924 */ 925 return fdt_del_partitions(blob, off); 926 } else { 927 ret = fdt_del_subnodes(blob, parent_offset); 928 if (ret < 0) { 929 printf("Can't remove subnodes: %s\n", 930 fdt_strerror(ret)); 931 return ret; 932 } 933 } 934 } 935 return 0; 936 } 937 938 int fdt_node_set_part_info(void *blob, int parent_offset, 939 struct mtd_device *dev) 940 { 941 struct list_head *pentry; 942 struct part_info *part; 943 struct reg_cell cell; 944 int off, ndepth = 0; 945 int part_num, ret; 946 char buf[64]; 947 948 ret = fdt_del_partitions(blob, parent_offset); 949 if (ret < 0) 950 return ret; 951 952 /* 953 * Check if it is nand {}; subnode, adjust 954 * the offset in this case 955 */ 956 off = fdt_next_node(blob, parent_offset, &ndepth); 957 if (off > 0 && ndepth == 1) 958 parent_offset = off; 959 960 part_num = 0; 961 list_for_each_prev(pentry, &dev->parts) { 962 int newoff; 963 964 part = list_entry(pentry, struct part_info, link); 965 966 debug("%2d: %-20s0x%08llx\t0x%08llx\t%d\n", 967 part_num, part->name, part->size, 968 part->offset, part->mask_flags); 969 970 sprintf(buf, "partition@%llx", part->offset); 971 add_sub: 972 ret = fdt_add_subnode(blob, parent_offset, buf); 973 if (ret == -FDT_ERR_NOSPACE) { 974 ret = fdt_increase_size(blob, 512); 975 if (!ret) 976 goto add_sub; 977 else 978 goto err_size; 979 } else if (ret < 0) { 980 printf("Can't add partition node: %s\n", 981 fdt_strerror(ret)); 982 return ret; 983 } 984 newoff = ret; 985 986 /* Check MTD_WRITEABLE_CMD flag */ 987 if (part->mask_flags & 1) { 988 add_ro: 989 ret = fdt_setprop(blob, newoff, "read_only", NULL, 0); 990 if (ret == -FDT_ERR_NOSPACE) { 991 ret = fdt_increase_size(blob, 512); 992 if (!ret) 993 goto add_ro; 994 else 995 goto err_size; 996 } else if (ret < 0) 997 goto err_prop; 998 } 999 1000 cell.r0 = cpu_to_fdt32(part->offset); 1001 cell.r1 = cpu_to_fdt32(part->size); 1002 add_reg: 1003 ret = fdt_setprop(blob, newoff, "reg", &cell, sizeof(cell)); 1004 if (ret == -FDT_ERR_NOSPACE) { 1005 ret = fdt_increase_size(blob, 512); 1006 if (!ret) 1007 goto add_reg; 1008 else 1009 goto err_size; 1010 } else if (ret < 0) 1011 goto err_prop; 1012 1013 add_label: 1014 ret = fdt_setprop_string(blob, newoff, "label", part->name); 1015 if (ret == -FDT_ERR_NOSPACE) { 1016 ret = fdt_increase_size(blob, 512); 1017 if (!ret) 1018 goto add_label; 1019 else 1020 goto err_size; 1021 } else if (ret < 0) 1022 goto err_prop; 1023 1024 part_num++; 1025 } 1026 return 0; 1027 err_size: 1028 printf("Can't increase blob size: %s\n", fdt_strerror(ret)); 1029 return ret; 1030 err_prop: 1031 printf("Can't add property: %s\n", fdt_strerror(ret)); 1032 return ret; 1033 } 1034 1035 /* 1036 * Update partitions in nor/nand nodes using info from 1037 * mtdparts environment variable. The nodes to update are 1038 * specified by node_info structure which contains mtd device 1039 * type and compatible string: E. g. the board code in 1040 * ft_board_setup() could use: 1041 * 1042 * struct node_info nodes[] = { 1043 * { "fsl,mpc5121-nfc", MTD_DEV_TYPE_NAND, }, 1044 * { "cfi-flash", MTD_DEV_TYPE_NOR, }, 1045 * }; 1046 * 1047 * fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); 1048 */ 1049 void fdt_fixup_mtdparts(void *blob, void *node_info, int node_info_size) 1050 { 1051 struct node_info *ni = node_info; 1052 struct mtd_device *dev; 1053 int i, idx; 1054 int noff; 1055 1056 if (mtdparts_init() != 0) 1057 return; 1058 1059 for (i = 0; i < node_info_size; i++) { 1060 idx = 0; 1061 noff = fdt_node_offset_by_compatible(blob, -1, ni[i].compat); 1062 while (noff != -FDT_ERR_NOTFOUND) { 1063 debug("%s: %s, mtd dev type %d\n", 1064 fdt_get_name(blob, noff, 0), 1065 ni[i].compat, ni[i].type); 1066 dev = device_find(ni[i].type, idx++); 1067 if (dev) { 1068 if (fdt_node_set_part_info(blob, noff, dev)) 1069 return; /* return on error */ 1070 } 1071 1072 /* Jump to next flash node */ 1073 noff = fdt_node_offset_by_compatible(blob, noff, 1074 ni[i].compat); 1075 } 1076 } 1077 } 1078 #endif 1079 1080 void fdt_del_node_and_alias(void *blob, const char *alias) 1081 { 1082 int off = fdt_path_offset(blob, alias); 1083 1084 if (off < 0) 1085 return; 1086 1087 fdt_del_node(blob, off); 1088 1089 off = fdt_path_offset(blob, "/aliases"); 1090 fdt_delprop(blob, off, alias); 1091 } 1092 1093 /* Max address size we deal with */ 1094 #define OF_MAX_ADDR_CELLS 4 1095 #define OF_BAD_ADDR FDT_ADDR_T_NONE 1096 #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ 1097 (ns) > 0) 1098 1099 /* Debug utility */ 1100 #ifdef DEBUG 1101 static void of_dump_addr(const char *s, const fdt32_t *addr, int na) 1102 { 1103 printf("%s", s); 1104 while(na--) 1105 printf(" %08x", *(addr++)); 1106 printf("\n"); 1107 } 1108 #else 1109 static void of_dump_addr(const char *s, const fdt32_t *addr, int na) { } 1110 #endif 1111 1112 /** 1113 * struct of_bus - Callbacks for bus specific translators 1114 * @name: A string used to identify this bus in debug output. 1115 * @addresses: The name of the DT property from which addresses are 1116 * to be read, typically "reg". 1117 * @match: Return non-zero if the node whose parent is at 1118 * parentoffset in the FDT blob corresponds to a bus 1119 * of this type, otherwise return zero. If NULL a match 1120 * is assumed. 1121 * @count_cells:Count how many cells (be32 values) a node whose parent 1122 * is at parentoffset in the FDT blob will require to 1123 * represent its address (written to *addrc) & size 1124 * (written to *sizec). 1125 * @map: Map the address addr from the address space of this 1126 * bus to that of its parent, making use of the ranges 1127 * read from DT to an array at range. na and ns are the 1128 * number of cells (be32 values) used to hold and address 1129 * or size, respectively, for this bus. pna is the number 1130 * of cells used to hold an address for the parent bus. 1131 * Returns the address in the address space of the parent 1132 * bus. 1133 * @translate: Update the value of the address cells at addr within an 1134 * FDT by adding offset to it. na specifies the number of 1135 * cells used to hold the address being translated. Returns 1136 * zero on success, non-zero on error. 1137 * 1138 * Each bus type will include a struct of_bus in the of_busses array, 1139 * providing implementations of some or all of the functions used to 1140 * match the bus & handle address translation for its children. 1141 */ 1142 struct of_bus { 1143 const char *name; 1144 const char *addresses; 1145 int (*match)(const void *blob, int parentoffset); 1146 void (*count_cells)(const void *blob, int parentoffset, 1147 int *addrc, int *sizec); 1148 u64 (*map)(fdt32_t *addr, const fdt32_t *range, 1149 int na, int ns, int pna); 1150 int (*translate)(fdt32_t *addr, u64 offset, int na); 1151 }; 1152 1153 /* Default translator (generic bus) */ 1154 void fdt_support_default_count_cells(const void *blob, int parentoffset, 1155 int *addrc, int *sizec) 1156 { 1157 const fdt32_t *prop; 1158 1159 if (addrc) 1160 *addrc = fdt_address_cells(blob, parentoffset); 1161 1162 if (sizec) { 1163 prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL); 1164 if (prop) 1165 *sizec = be32_to_cpup(prop); 1166 else 1167 *sizec = 1; 1168 } 1169 } 1170 1171 static u64 of_bus_default_map(fdt32_t *addr, const fdt32_t *range, 1172 int na, int ns, int pna) 1173 { 1174 u64 cp, s, da; 1175 1176 cp = fdt_read_number(range, na); 1177 s = fdt_read_number(range + na + pna, ns); 1178 da = fdt_read_number(addr, na); 1179 1180 debug("OF: default map, cp=%" PRIu64 ", s=%" PRIu64 1181 ", da=%" PRIu64 "\n", cp, s, da); 1182 1183 if (da < cp || da >= (cp + s)) 1184 return OF_BAD_ADDR; 1185 return da - cp; 1186 } 1187 1188 static int of_bus_default_translate(fdt32_t *addr, u64 offset, int na) 1189 { 1190 u64 a = fdt_read_number(addr, na); 1191 memset(addr, 0, na * 4); 1192 a += offset; 1193 if (na > 1) 1194 addr[na - 2] = cpu_to_fdt32(a >> 32); 1195 addr[na - 1] = cpu_to_fdt32(a & 0xffffffffu); 1196 1197 return 0; 1198 } 1199 1200 #ifdef CONFIG_OF_ISA_BUS 1201 1202 /* ISA bus translator */ 1203 static int of_bus_isa_match(const void *blob, int parentoffset) 1204 { 1205 const char *name; 1206 1207 name = fdt_get_name(blob, parentoffset, NULL); 1208 if (!name) 1209 return 0; 1210 1211 return !strcmp(name, "isa"); 1212 } 1213 1214 static void of_bus_isa_count_cells(const void *blob, int parentoffset, 1215 int *addrc, int *sizec) 1216 { 1217 if (addrc) 1218 *addrc = 2; 1219 if (sizec) 1220 *sizec = 1; 1221 } 1222 1223 static u64 of_bus_isa_map(fdt32_t *addr, const fdt32_t *range, 1224 int na, int ns, int pna) 1225 { 1226 u64 cp, s, da; 1227 1228 /* Check address type match */ 1229 if ((addr[0] ^ range[0]) & cpu_to_be32(1)) 1230 return OF_BAD_ADDR; 1231 1232 cp = fdt_read_number(range + 1, na - 1); 1233 s = fdt_read_number(range + na + pna, ns); 1234 da = fdt_read_number(addr + 1, na - 1); 1235 1236 debug("OF: ISA map, cp=%" PRIu64 ", s=%" PRIu64 1237 ", da=%" PRIu64 "\n", cp, s, da); 1238 1239 if (da < cp || da >= (cp + s)) 1240 return OF_BAD_ADDR; 1241 return da - cp; 1242 } 1243 1244 static int of_bus_isa_translate(fdt32_t *addr, u64 offset, int na) 1245 { 1246 return of_bus_default_translate(addr + 1, offset, na - 1); 1247 } 1248 1249 #endif /* CONFIG_OF_ISA_BUS */ 1250 1251 /* Array of bus specific translators */ 1252 static struct of_bus of_busses[] = { 1253 #ifdef CONFIG_OF_ISA_BUS 1254 /* ISA */ 1255 { 1256 .name = "isa", 1257 .addresses = "reg", 1258 .match = of_bus_isa_match, 1259 .count_cells = of_bus_isa_count_cells, 1260 .map = of_bus_isa_map, 1261 .translate = of_bus_isa_translate, 1262 }, 1263 #endif /* CONFIG_OF_ISA_BUS */ 1264 /* Default */ 1265 { 1266 .name = "default", 1267 .addresses = "reg", 1268 .count_cells = fdt_support_default_count_cells, 1269 .map = of_bus_default_map, 1270 .translate = of_bus_default_translate, 1271 }, 1272 }; 1273 1274 static struct of_bus *of_match_bus(const void *blob, int parentoffset) 1275 { 1276 struct of_bus *bus; 1277 1278 if (ARRAY_SIZE(of_busses) == 1) 1279 return of_busses; 1280 1281 for (bus = of_busses; bus; bus++) { 1282 if (!bus->match || bus->match(blob, parentoffset)) 1283 return bus; 1284 } 1285 1286 /* 1287 * We should always have matched the default bus at least, since 1288 * it has a NULL match field. If we didn't then it somehow isn't 1289 * in the of_busses array or something equally catastrophic has 1290 * gone wrong. 1291 */ 1292 assert(0); 1293 return NULL; 1294 } 1295 1296 static int of_translate_one(const void *blob, int parent, struct of_bus *bus, 1297 struct of_bus *pbus, fdt32_t *addr, 1298 int na, int ns, int pna, const char *rprop) 1299 { 1300 const fdt32_t *ranges; 1301 int rlen; 1302 int rone; 1303 u64 offset = OF_BAD_ADDR; 1304 1305 /* Normally, an absence of a "ranges" property means we are 1306 * crossing a non-translatable boundary, and thus the addresses 1307 * below the current not cannot be converted to CPU physical ones. 1308 * Unfortunately, while this is very clear in the spec, it's not 1309 * what Apple understood, and they do have things like /uni-n or 1310 * /ht nodes with no "ranges" property and a lot of perfectly 1311 * useable mapped devices below them. Thus we treat the absence of 1312 * "ranges" as equivalent to an empty "ranges" property which means 1313 * a 1:1 translation at that level. It's up to the caller not to try 1314 * to translate addresses that aren't supposed to be translated in 1315 * the first place. --BenH. 1316 */ 1317 ranges = fdt_getprop(blob, parent, rprop, &rlen); 1318 if (ranges == NULL || rlen == 0) { 1319 offset = fdt_read_number(addr, na); 1320 memset(addr, 0, pna * 4); 1321 debug("OF: no ranges, 1:1 translation\n"); 1322 goto finish; 1323 } 1324 1325 debug("OF: walking ranges...\n"); 1326 1327 /* Now walk through the ranges */ 1328 rlen /= 4; 1329 rone = na + pna + ns; 1330 for (; rlen >= rone; rlen -= rone, ranges += rone) { 1331 offset = bus->map(addr, ranges, na, ns, pna); 1332 if (offset != OF_BAD_ADDR) 1333 break; 1334 } 1335 if (offset == OF_BAD_ADDR) { 1336 debug("OF: not found !\n"); 1337 return 1; 1338 } 1339 memcpy(addr, ranges + na, 4 * pna); 1340 1341 finish: 1342 of_dump_addr("OF: parent translation for:", addr, pna); 1343 debug("OF: with offset: %" PRIu64 "\n", offset); 1344 1345 /* Translate it into parent bus space */ 1346 return pbus->translate(addr, offset, pna); 1347 } 1348 1349 /* 1350 * Translate an address from the device-tree into a CPU physical address, 1351 * this walks up the tree and applies the various bus mappings on the 1352 * way. 1353 * 1354 * Note: We consider that crossing any level with #size-cells == 0 to mean 1355 * that translation is impossible (that is we are not dealing with a value 1356 * that can be mapped to a cpu physical address). This is not really specified 1357 * that way, but this is traditionally the way IBM at least do things 1358 */ 1359 static u64 __of_translate_address(const void *blob, int node_offset, 1360 const fdt32_t *in_addr, const char *rprop) 1361 { 1362 int parent; 1363 struct of_bus *bus, *pbus; 1364 fdt32_t addr[OF_MAX_ADDR_CELLS]; 1365 int na, ns, pna, pns; 1366 u64 result = OF_BAD_ADDR; 1367 1368 debug("OF: ** translation for device %s **\n", 1369 fdt_get_name(blob, node_offset, NULL)); 1370 1371 /* Get parent & match bus type */ 1372 parent = fdt_parent_offset(blob, node_offset); 1373 if (parent < 0) 1374 goto bail; 1375 bus = of_match_bus(blob, parent); 1376 1377 /* Cound address cells & copy address locally */ 1378 bus->count_cells(blob, parent, &na, &ns); 1379 if (!OF_CHECK_COUNTS(na, ns)) { 1380 printf("%s: Bad cell count for %s\n", __FUNCTION__, 1381 fdt_get_name(blob, node_offset, NULL)); 1382 goto bail; 1383 } 1384 memcpy(addr, in_addr, na * 4); 1385 1386 debug("OF: bus is %s (na=%d, ns=%d) on %s\n", 1387 bus->name, na, ns, fdt_get_name(blob, parent, NULL)); 1388 of_dump_addr("OF: translating address:", addr, na); 1389 1390 /* Translate */ 1391 for (;;) { 1392 /* Switch to parent bus */ 1393 node_offset = parent; 1394 parent = fdt_parent_offset(blob, node_offset); 1395 1396 /* If root, we have finished */ 1397 if (parent < 0) { 1398 debug("OF: reached root node\n"); 1399 result = fdt_read_number(addr, na); 1400 break; 1401 } 1402 1403 /* Get new parent bus and counts */ 1404 pbus = of_match_bus(blob, parent); 1405 pbus->count_cells(blob, parent, &pna, &pns); 1406 if (!OF_CHECK_COUNTS(pna, pns)) { 1407 printf("%s: Bad cell count for %s\n", __FUNCTION__, 1408 fdt_get_name(blob, node_offset, NULL)); 1409 break; 1410 } 1411 1412 debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n", 1413 pbus->name, pna, pns, fdt_get_name(blob, parent, NULL)); 1414 1415 /* Apply bus translation */ 1416 if (of_translate_one(blob, node_offset, bus, pbus, 1417 addr, na, ns, pna, rprop)) 1418 break; 1419 1420 /* Complete the move up one level */ 1421 na = pna; 1422 ns = pns; 1423 bus = pbus; 1424 1425 of_dump_addr("OF: one level translation:", addr, na); 1426 } 1427 bail: 1428 1429 return result; 1430 } 1431 1432 u64 fdt_translate_address(const void *blob, int node_offset, 1433 const fdt32_t *in_addr) 1434 { 1435 return __of_translate_address(blob, node_offset, in_addr, "ranges"); 1436 } 1437 1438 /** 1439 * fdt_node_offset_by_compat_reg: Find a node that matches compatiable and 1440 * who's reg property matches a physical cpu address 1441 * 1442 * @blob: ptr to device tree 1443 * @compat: compatiable string to match 1444 * @compat_off: property name 1445 * 1446 */ 1447 int fdt_node_offset_by_compat_reg(void *blob, const char *compat, 1448 phys_addr_t compat_off) 1449 { 1450 int len, off = fdt_node_offset_by_compatible(blob, -1, compat); 1451 while (off != -FDT_ERR_NOTFOUND) { 1452 const fdt32_t *reg = fdt_getprop(blob, off, "reg", &len); 1453 if (reg) { 1454 if (compat_off == fdt_translate_address(blob, off, reg)) 1455 return off; 1456 } 1457 off = fdt_node_offset_by_compatible(blob, off, compat); 1458 } 1459 1460 return -FDT_ERR_NOTFOUND; 1461 } 1462 1463 /** 1464 * fdt_alloc_phandle: Return next free phandle value 1465 * 1466 * @blob: ptr to device tree 1467 */ 1468 int fdt_alloc_phandle(void *blob) 1469 { 1470 int offset; 1471 uint32_t phandle = 0; 1472 1473 for (offset = fdt_next_node(blob, -1, NULL); offset >= 0; 1474 offset = fdt_next_node(blob, offset, NULL)) { 1475 phandle = max(phandle, fdt_get_phandle(blob, offset)); 1476 } 1477 1478 return phandle + 1; 1479 } 1480 1481 /* 1482 * fdt_set_phandle: Create a phandle property for the given node 1483 * 1484 * @fdt: ptr to device tree 1485 * @nodeoffset: node to update 1486 * @phandle: phandle value to set (must be unique) 1487 */ 1488 int fdt_set_phandle(void *fdt, int nodeoffset, uint32_t phandle) 1489 { 1490 int ret; 1491 1492 #ifdef DEBUG 1493 int off = fdt_node_offset_by_phandle(fdt, phandle); 1494 1495 if ((off >= 0) && (off != nodeoffset)) { 1496 char buf[64]; 1497 1498 fdt_get_path(fdt, nodeoffset, buf, sizeof(buf)); 1499 printf("Trying to update node %s with phandle %u ", 1500 buf, phandle); 1501 1502 fdt_get_path(fdt, off, buf, sizeof(buf)); 1503 printf("that already exists in node %s.\n", buf); 1504 return -FDT_ERR_BADPHANDLE; 1505 } 1506 #endif 1507 1508 ret = fdt_setprop_cell(fdt, nodeoffset, "phandle", phandle); 1509 if (ret < 0) 1510 return ret; 1511 1512 /* 1513 * For now, also set the deprecated "linux,phandle" property, so that we 1514 * don't break older kernels. 1515 */ 1516 ret = fdt_setprop_cell(fdt, nodeoffset, "linux,phandle", phandle); 1517 1518 return ret; 1519 } 1520 1521 /* 1522 * fdt_create_phandle: Create a phandle property for the given node 1523 * 1524 * @fdt: ptr to device tree 1525 * @nodeoffset: node to update 1526 */ 1527 unsigned int fdt_create_phandle(void *fdt, int nodeoffset) 1528 { 1529 /* see if there is a phandle already */ 1530 int phandle = fdt_get_phandle(fdt, nodeoffset); 1531 1532 /* if we got 0, means no phandle so create one */ 1533 if (phandle == 0) { 1534 int ret; 1535 1536 phandle = fdt_alloc_phandle(fdt); 1537 ret = fdt_set_phandle(fdt, nodeoffset, phandle); 1538 if (ret < 0) { 1539 printf("Can't set phandle %u: %s\n", phandle, 1540 fdt_strerror(ret)); 1541 return 0; 1542 } 1543 } 1544 1545 return phandle; 1546 } 1547 1548 /* 1549 * fdt_set_node_status: Set status for the given node 1550 * 1551 * @fdt: ptr to device tree 1552 * @nodeoffset: node to update 1553 * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, 1554 * FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE 1555 * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE 1556 */ 1557 int fdt_set_node_status(void *fdt, int nodeoffset, 1558 enum fdt_status status, unsigned int error_code) 1559 { 1560 char buf[16]; 1561 int ret = 0; 1562 1563 if (nodeoffset < 0) 1564 return nodeoffset; 1565 1566 switch (status) { 1567 case FDT_STATUS_OKAY: 1568 ret = fdt_setprop_string(fdt, nodeoffset, "status", "okay"); 1569 break; 1570 case FDT_STATUS_DISABLED: 1571 ret = fdt_setprop_string(fdt, nodeoffset, "status", "disabled"); 1572 break; 1573 case FDT_STATUS_FAIL: 1574 ret = fdt_setprop_string(fdt, nodeoffset, "status", "fail"); 1575 break; 1576 case FDT_STATUS_FAIL_ERROR_CODE: 1577 sprintf(buf, "fail-%d", error_code); 1578 ret = fdt_setprop_string(fdt, nodeoffset, "status", buf); 1579 break; 1580 default: 1581 printf("Invalid fdt status: %x\n", status); 1582 ret = -1; 1583 break; 1584 } 1585 1586 return ret; 1587 } 1588 1589 /* 1590 * fdt_set_status_by_alias: Set status for the given node given an alias 1591 * 1592 * @fdt: ptr to device tree 1593 * @alias: alias of node to update 1594 * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, 1595 * FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE 1596 * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE 1597 */ 1598 int fdt_set_status_by_alias(void *fdt, const char* alias, 1599 enum fdt_status status, unsigned int error_code) 1600 { 1601 int offset = fdt_path_offset(fdt, alias); 1602 1603 return fdt_set_node_status(fdt, offset, status, error_code); 1604 } 1605 1606 #if defined(CONFIG_VIDEO) || defined(CONFIG_LCD) 1607 int fdt_add_edid(void *blob, const char *compat, unsigned char *edid_buf) 1608 { 1609 int noff; 1610 int ret; 1611 1612 noff = fdt_node_offset_by_compatible(blob, -1, compat); 1613 if (noff != -FDT_ERR_NOTFOUND) { 1614 debug("%s: %s\n", fdt_get_name(blob, noff, 0), compat); 1615 add_edid: 1616 ret = fdt_setprop(blob, noff, "edid", edid_buf, 128); 1617 if (ret == -FDT_ERR_NOSPACE) { 1618 ret = fdt_increase_size(blob, 512); 1619 if (!ret) 1620 goto add_edid; 1621 else 1622 goto err_size; 1623 } else if (ret < 0) { 1624 printf("Can't add property: %s\n", fdt_strerror(ret)); 1625 return ret; 1626 } 1627 } 1628 return 0; 1629 err_size: 1630 printf("Can't increase blob size: %s\n", fdt_strerror(ret)); 1631 return ret; 1632 } 1633 #endif 1634 1635 /* 1636 * Verify the physical address of device tree node for a given alias 1637 * 1638 * This function locates the device tree node of a given alias, and then 1639 * verifies that the physical address of that device matches the given 1640 * parameter. It displays a message if there is a mismatch. 1641 * 1642 * Returns 1 on success, 0 on failure 1643 */ 1644 int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr) 1645 { 1646 const char *path; 1647 const fdt32_t *reg; 1648 int node, len; 1649 u64 dt_addr; 1650 1651 path = fdt_getprop(fdt, anode, alias, NULL); 1652 if (!path) { 1653 /* If there's no such alias, then it's not a failure */ 1654 return 1; 1655 } 1656 1657 node = fdt_path_offset(fdt, path); 1658 if (node < 0) { 1659 printf("Warning: device tree alias '%s' points to invalid " 1660 "node %s.\n", alias, path); 1661 return 0; 1662 } 1663 1664 reg = fdt_getprop(fdt, node, "reg", &len); 1665 if (!reg) { 1666 printf("Warning: device tree node '%s' has no address.\n", 1667 path); 1668 return 0; 1669 } 1670 1671 dt_addr = fdt_translate_address(fdt, node, reg); 1672 if (addr != dt_addr) { 1673 printf("Warning: U-Boot configured device %s at address %" 1674 PRIx64 ",\n but the device tree has it address %" 1675 PRIx64 ".\n", alias, addr, dt_addr); 1676 return 0; 1677 } 1678 1679 return 1; 1680 } 1681 1682 /* 1683 * Returns the base address of an SOC or PCI node 1684 */ 1685 u64 fdt_get_base_address(const void *fdt, int node) 1686 { 1687 int size; 1688 const fdt32_t *prop; 1689 1690 prop = fdt_getprop(fdt, node, "reg", &size); 1691 1692 return prop ? fdt_translate_address(fdt, node, prop) : 0; 1693 } 1694 1695 /* 1696 * Read a property of size <prop_len>. Currently only supports 1 or 2 cells. 1697 */ 1698 static int fdt_read_prop(const fdt32_t *prop, int prop_len, int cell_off, 1699 uint64_t *val, int cells) 1700 { 1701 const fdt32_t *prop32 = &prop[cell_off]; 1702 const fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off]; 1703 1704 if ((cell_off + cells) > prop_len) 1705 return -FDT_ERR_NOSPACE; 1706 1707 switch (cells) { 1708 case 1: 1709 *val = fdt32_to_cpu(*prop32); 1710 break; 1711 case 2: 1712 *val = fdt64_to_cpu(*prop64); 1713 break; 1714 default: 1715 return -FDT_ERR_NOSPACE; 1716 } 1717 1718 return 0; 1719 } 1720 1721 /** 1722 * fdt_read_range - Read a node's n'th range property 1723 * 1724 * @fdt: ptr to device tree 1725 * @node: offset of node 1726 * @n: range index 1727 * @child_addr: pointer to storage for the "child address" field 1728 * @addr: pointer to storage for the CPU view translated physical start 1729 * @len: pointer to storage for the range length 1730 * 1731 * Convenience function that reads and interprets a specific range out of 1732 * a number of the "ranges" property array. 1733 */ 1734 int fdt_read_range(void *fdt, int node, int n, uint64_t *child_addr, 1735 uint64_t *addr, uint64_t *len) 1736 { 1737 int pnode = fdt_parent_offset(fdt, node); 1738 const fdt32_t *ranges; 1739 int pacells; 1740 int acells; 1741 int scells; 1742 int ranges_len; 1743 int cell = 0; 1744 int r = 0; 1745 1746 /* 1747 * The "ranges" property is an array of 1748 * { <child address> <parent address> <size in child address space> } 1749 * 1750 * All 3 elements can span a diffent number of cells. Fetch their size. 1751 */ 1752 pacells = fdt_getprop_u32_default_node(fdt, pnode, 0, "#address-cells", 1); 1753 acells = fdt_getprop_u32_default_node(fdt, node, 0, "#address-cells", 1); 1754 scells = fdt_getprop_u32_default_node(fdt, node, 0, "#size-cells", 1); 1755 1756 /* Now try to get the ranges property */ 1757 ranges = fdt_getprop(fdt, node, "ranges", &ranges_len); 1758 if (!ranges) 1759 return -FDT_ERR_NOTFOUND; 1760 ranges_len /= sizeof(uint32_t); 1761 1762 /* Jump to the n'th entry */ 1763 cell = n * (pacells + acells + scells); 1764 1765 /* Read <child address> */ 1766 if (child_addr) { 1767 r = fdt_read_prop(ranges, ranges_len, cell, child_addr, 1768 acells); 1769 if (r) 1770 return r; 1771 } 1772 cell += acells; 1773 1774 /* Read <parent address> */ 1775 if (addr) 1776 *addr = fdt_translate_address(fdt, node, ranges + cell); 1777 cell += pacells; 1778 1779 /* Read <size in child address space> */ 1780 if (len) { 1781 r = fdt_read_prop(ranges, ranges_len, cell, len, scells); 1782 if (r) 1783 return r; 1784 } 1785 1786 return 0; 1787 } 1788 1789 /** 1790 * fdt_setup_simplefb_node - Fill and enable a simplefb node 1791 * 1792 * @fdt: ptr to device tree 1793 * @node: offset of the simplefb node 1794 * @base_address: framebuffer base address 1795 * @width: width in pixels 1796 * @height: height in pixels 1797 * @stride: bytes per line 1798 * @format: pixel format string 1799 * 1800 * Convenience function to fill and enable a simplefb node. 1801 */ 1802 int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width, 1803 u32 height, u32 stride, const char *format) 1804 { 1805 char name[32]; 1806 fdt32_t cells[4]; 1807 int i, addrc, sizec, ret; 1808 1809 fdt_support_default_count_cells(fdt, fdt_parent_offset(fdt, node), 1810 &addrc, &sizec); 1811 i = 0; 1812 if (addrc == 2) 1813 cells[i++] = cpu_to_fdt32(base_address >> 32); 1814 cells[i++] = cpu_to_fdt32(base_address); 1815 if (sizec == 2) 1816 cells[i++] = 0; 1817 cells[i++] = cpu_to_fdt32(height * stride); 1818 1819 ret = fdt_setprop(fdt, node, "reg", cells, sizeof(cells[0]) * i); 1820 if (ret < 0) 1821 return ret; 1822 1823 snprintf(name, sizeof(name), "framebuffer@%" PRIx64, base_address); 1824 ret = fdt_set_name(fdt, node, name); 1825 if (ret < 0) 1826 return ret; 1827 1828 ret = fdt_setprop_u32(fdt, node, "width", width); 1829 if (ret < 0) 1830 return ret; 1831 1832 ret = fdt_setprop_u32(fdt, node, "height", height); 1833 if (ret < 0) 1834 return ret; 1835 1836 ret = fdt_setprop_u32(fdt, node, "stride", stride); 1837 if (ret < 0) 1838 return ret; 1839 1840 ret = fdt_setprop_string(fdt, node, "format", format); 1841 if (ret < 0) 1842 return ret; 1843 1844 ret = fdt_setprop_string(fdt, node, "status", "okay"); 1845 if (ret < 0) 1846 return ret; 1847 1848 return 0; 1849 } 1850 1851 /* 1852 * Update native-mode in display-timings from display environment variable. 1853 * The node to update are specified by path. 1854 */ 1855 int fdt_fixup_display(void *blob, const char *path, const char *display) 1856 { 1857 int off, toff; 1858 1859 if (!display || !path) 1860 return -FDT_ERR_NOTFOUND; 1861 1862 toff = fdt_path_offset(blob, path); 1863 if (toff >= 0) 1864 toff = fdt_subnode_offset(blob, toff, "display-timings"); 1865 if (toff < 0) 1866 return toff; 1867 1868 for (off = fdt_first_subnode(blob, toff); 1869 off >= 0; 1870 off = fdt_next_subnode(blob, off)) { 1871 uint32_t h = fdt_get_phandle(blob, off); 1872 debug("%s:0x%x\n", fdt_get_name(blob, off, NULL), 1873 fdt32_to_cpu(h)); 1874 if (strcasecmp(fdt_get_name(blob, off, NULL), display) == 0) 1875 return fdt_setprop_u32(blob, toff, "native-mode", h); 1876 } 1877 return toff; 1878 } 1879 1880 #ifdef CONFIG_OF_LIBFDT_OVERLAY 1881 /** 1882 * fdt_overlay_apply_verbose - Apply an overlay with verbose error reporting 1883 * 1884 * @fdt: ptr to device tree 1885 * @fdto: ptr to device tree overlay 1886 * 1887 * Convenience function to apply an overlay and display helpful messages 1888 * in the case of an error 1889 */ 1890 int fdt_overlay_apply_verbose(void *fdt, void *fdto) 1891 { 1892 int err; 1893 bool has_symbols; 1894 1895 err = fdt_path_offset(fdt, "/__symbols__"); 1896 has_symbols = err >= 0; 1897 1898 err = fdt_overlay_apply(fdt, fdto); 1899 if (err < 0) { 1900 printf("failed on fdt_overlay_apply(): %s\n", 1901 fdt_strerror(err)); 1902 if (!has_symbols) { 1903 printf("base fdt does did not have a /__symbols__ node\n"); 1904 printf("make sure you've compiled with -@\n"); 1905 } 1906 } 1907 return err; 1908 } 1909 #endif 1910