1 /* 2 * Copyright (c) 2011 The Chromium OS Authors. 3 * SPDX-License-Identifier: GPL-2.0+ 4 */ 5 6 #ifndef USE_HOSTCC 7 #include <common.h> 8 #include <serial.h> 9 #include <libfdt.h> 10 #include <fdtdec.h> 11 12 #include <asm/gpio.h> 13 14 DECLARE_GLOBAL_DATA_PTR; 15 16 /* 17 * Here are the type we know about. One day we might allow drivers to 18 * register. For now we just put them here. The COMPAT macro allows us to 19 * turn this into a sparse list later, and keeps the ID with the name. 20 */ 21 #define COMPAT(id, name) name 22 static const char * const compat_names[COMPAT_COUNT] = { 23 COMPAT(UNKNOWN, "<none>"), 24 COMPAT(NVIDIA_TEGRA20_USB, "nvidia,tegra20-ehci"), 25 COMPAT(NVIDIA_TEGRA30_USB, "nvidia,tegra30-ehci"), 26 COMPAT(NVIDIA_TEGRA114_USB, "nvidia,tegra114-ehci"), 27 COMPAT(NVIDIA_TEGRA114_I2C, "nvidia,tegra114-i2c"), 28 COMPAT(NVIDIA_TEGRA20_I2C, "nvidia,tegra20-i2c"), 29 COMPAT(NVIDIA_TEGRA20_DVC, "nvidia,tegra20-i2c-dvc"), 30 COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"), 31 COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"), 32 COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"), 33 COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"), 34 COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"), 35 COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"), 36 COMPAT(NVIDIA_TEGRA124_SDMMC, "nvidia,tegra124-sdhci"), 37 COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"), 38 COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"), 39 COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"), 40 COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"), 41 COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"), 42 COMPAT(SMSC_LAN9215, "smsc,lan9215"), 43 COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"), 44 COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"), 45 COMPAT(SAMSUNG_EXYNOS5_SOUND, "samsung,exynos-sound"), 46 COMPAT(WOLFSON_WM8994_CODEC, "wolfson,wm8994-codec"), 47 COMPAT(SAMSUNG_EXYNOS_SPI, "samsung,exynos-spi"), 48 COMPAT(GOOGLE_CROS_EC, "google,cros-ec"), 49 COMPAT(GOOGLE_CROS_EC_KEYB, "google,cros-ec-keyb"), 50 COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"), 51 COMPAT(SAMSUNG_EXYNOS5_XHCI, "samsung,exynos5250-xhci"), 52 COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"), 53 COMPAT(SAMSUNG_EXYNOS5_USB3_PHY, "samsung,exynos5250-usb3-phy"), 54 COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"), 55 COMPAT(SAMSUNG_EXYNOS_FIMD, "samsung,exynos-fimd"), 56 COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"), 57 COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"), 58 COMPAT(SAMSUNG_EXYNOS_DWMMC, "samsung,exynos-dwmmc"), 59 COMPAT(SAMSUNG_EXYNOS_MMC, "samsung,exynos-mmc"), 60 COMPAT(SAMSUNG_EXYNOS_SERIAL, "samsung,exynos4210-uart"), 61 COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"), 62 COMPAT(GENERIC_SPI_FLASH, "spi-flash"), 63 COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"), 64 COMPAT(INFINEON_SLB9635_TPM, "infineon,slb9635-tpm"), 65 COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645-tpm"), 66 COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"), 67 COMPAT(SANDBOX_HOST_EMULATION, "sandbox,host-emulation"), 68 COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"), 69 COMPAT(TI_TPS65090, "ti,tps65090"), 70 COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"), 71 }; 72 73 const char *fdtdec_get_compatible(enum fdt_compat_id id) 74 { 75 /* We allow reading of the 'unknown' ID for testing purposes */ 76 assert(id >= 0 && id < COMPAT_COUNT); 77 return compat_names[id]; 78 } 79 80 fdt_addr_t fdtdec_get_addr_size(const void *blob, int node, 81 const char *prop_name, fdt_size_t *sizep) 82 { 83 const fdt_addr_t *cell; 84 int len; 85 86 debug("%s: %s: ", __func__, prop_name); 87 cell = fdt_getprop(blob, node, prop_name, &len); 88 if (cell && ((!sizep && len == sizeof(fdt_addr_t)) || 89 len == sizeof(fdt_addr_t) * 2)) { 90 fdt_addr_t addr = fdt_addr_to_cpu(*cell); 91 if (sizep) { 92 const fdt_size_t *size; 93 94 size = (fdt_size_t *)((char *)cell + 95 sizeof(fdt_addr_t)); 96 *sizep = fdt_size_to_cpu(*size); 97 debug("addr=%08lx, size=%08x\n", 98 (ulong)addr, *sizep); 99 } else { 100 debug("%08lx\n", (ulong)addr); 101 } 102 return addr; 103 } 104 debug("(not found)\n"); 105 return FDT_ADDR_T_NONE; 106 } 107 108 fdt_addr_t fdtdec_get_addr(const void *blob, int node, 109 const char *prop_name) 110 { 111 return fdtdec_get_addr_size(blob, node, prop_name, NULL); 112 } 113 114 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name, 115 uint64_t default_val) 116 { 117 const uint64_t *cell64; 118 int length; 119 120 cell64 = fdt_getprop(blob, node, prop_name, &length); 121 if (!cell64 || length < sizeof(*cell64)) 122 return default_val; 123 124 return fdt64_to_cpu(*cell64); 125 } 126 127 int fdtdec_get_is_enabled(const void *blob, int node) 128 { 129 const char *cell; 130 131 /* 132 * It should say "okay", so only allow that. Some fdts use "ok" but 133 * this is a bug. Please fix your device tree source file. See here 134 * for discussion: 135 * 136 * http://www.mail-archive.com/u-boot@lists.denx.de/msg71598.html 137 */ 138 cell = fdt_getprop(blob, node, "status", NULL); 139 if (cell) 140 return 0 == strcmp(cell, "okay"); 141 return 1; 142 } 143 144 enum fdt_compat_id fdtdec_lookup(const void *blob, int node) 145 { 146 enum fdt_compat_id id; 147 148 /* Search our drivers */ 149 for (id = COMPAT_UNKNOWN; id < COMPAT_COUNT; id++) 150 if (0 == fdt_node_check_compatible(blob, node, 151 compat_names[id])) 152 return id; 153 return COMPAT_UNKNOWN; 154 } 155 156 int fdtdec_next_compatible(const void *blob, int node, 157 enum fdt_compat_id id) 158 { 159 return fdt_node_offset_by_compatible(blob, node, compat_names[id]); 160 } 161 162 int fdtdec_next_compatible_subnode(const void *blob, int node, 163 enum fdt_compat_id id, int *depthp) 164 { 165 do { 166 node = fdt_next_node(blob, node, depthp); 167 } while (*depthp > 1); 168 169 /* If this is a direct subnode, and compatible, return it */ 170 if (*depthp == 1 && 0 == fdt_node_check_compatible( 171 blob, node, compat_names[id])) 172 return node; 173 174 return -FDT_ERR_NOTFOUND; 175 } 176 177 int fdtdec_next_alias(const void *blob, const char *name, 178 enum fdt_compat_id id, int *upto) 179 { 180 #define MAX_STR_LEN 20 181 char str[MAX_STR_LEN + 20]; 182 int node, err; 183 184 /* snprintf() is not available */ 185 assert(strlen(name) < MAX_STR_LEN); 186 sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto); 187 node = fdt_path_offset(blob, str); 188 if (node < 0) 189 return node; 190 err = fdt_node_check_compatible(blob, node, compat_names[id]); 191 if (err < 0) 192 return err; 193 if (err) 194 return -FDT_ERR_NOTFOUND; 195 (*upto)++; 196 return node; 197 } 198 199 int fdtdec_find_aliases_for_id(const void *blob, const char *name, 200 enum fdt_compat_id id, int *node_list, int maxcount) 201 { 202 memset(node_list, '\0', sizeof(*node_list) * maxcount); 203 204 return fdtdec_add_aliases_for_id(blob, name, id, node_list, maxcount); 205 } 206 207 /* TODO: Can we tighten this code up a little? */ 208 int fdtdec_add_aliases_for_id(const void *blob, const char *name, 209 enum fdt_compat_id id, int *node_list, int maxcount) 210 { 211 int name_len = strlen(name); 212 int nodes[maxcount]; 213 int num_found = 0; 214 int offset, node; 215 int alias_node; 216 int count; 217 int i, j; 218 219 /* find the alias node if present */ 220 alias_node = fdt_path_offset(blob, "/aliases"); 221 222 /* 223 * start with nothing, and we can assume that the root node can't 224 * match 225 */ 226 memset(nodes, '\0', sizeof(nodes)); 227 228 /* First find all the compatible nodes */ 229 for (node = count = 0; node >= 0 && count < maxcount;) { 230 node = fdtdec_next_compatible(blob, node, id); 231 if (node >= 0) 232 nodes[count++] = node; 233 } 234 if (node >= 0) 235 debug("%s: warning: maxcount exceeded with alias '%s'\n", 236 __func__, name); 237 238 /* Now find all the aliases */ 239 for (offset = fdt_first_property_offset(blob, alias_node); 240 offset > 0; 241 offset = fdt_next_property_offset(blob, offset)) { 242 const struct fdt_property *prop; 243 const char *path; 244 int number; 245 int found; 246 247 node = 0; 248 prop = fdt_get_property_by_offset(blob, offset, NULL); 249 path = fdt_string(blob, fdt32_to_cpu(prop->nameoff)); 250 if (prop->len && 0 == strncmp(path, name, name_len)) 251 node = fdt_path_offset(blob, prop->data); 252 if (node <= 0) 253 continue; 254 255 /* Get the alias number */ 256 number = simple_strtoul(path + name_len, NULL, 10); 257 if (number < 0 || number >= maxcount) { 258 debug("%s: warning: alias '%s' is out of range\n", 259 __func__, path); 260 continue; 261 } 262 263 /* Make sure the node we found is actually in our list! */ 264 found = -1; 265 for (j = 0; j < count; j++) 266 if (nodes[j] == node) { 267 found = j; 268 break; 269 } 270 271 if (found == -1) { 272 debug("%s: warning: alias '%s' points to a node " 273 "'%s' that is missing or is not compatible " 274 " with '%s'\n", __func__, path, 275 fdt_get_name(blob, node, NULL), 276 compat_names[id]); 277 continue; 278 } 279 280 /* 281 * Add this node to our list in the right place, and mark 282 * it as done. 283 */ 284 if (fdtdec_get_is_enabled(blob, node)) { 285 if (node_list[number]) { 286 debug("%s: warning: alias '%s' requires that " 287 "a node be placed in the list in a " 288 "position which is already filled by " 289 "node '%s'\n", __func__, path, 290 fdt_get_name(blob, node, NULL)); 291 continue; 292 } 293 node_list[number] = node; 294 if (number >= num_found) 295 num_found = number + 1; 296 } 297 nodes[found] = 0; 298 } 299 300 /* Add any nodes not mentioned by an alias */ 301 for (i = j = 0; i < maxcount; i++) { 302 if (!node_list[i]) { 303 for (; j < maxcount; j++) 304 if (nodes[j] && 305 fdtdec_get_is_enabled(blob, nodes[j])) 306 break; 307 308 /* Have we run out of nodes to add? */ 309 if (j == maxcount) 310 break; 311 312 assert(!node_list[i]); 313 node_list[i] = nodes[j++]; 314 if (i >= num_found) 315 num_found = i + 1; 316 } 317 } 318 319 return num_found; 320 } 321 322 int fdtdec_check_fdt(void) 323 { 324 /* 325 * We must have an FDT, but we cannot panic() yet since the console 326 * is not ready. So for now, just assert(). Boards which need an early 327 * FDT (prior to console ready) will need to make their own 328 * arrangements and do their own checks. 329 */ 330 assert(!fdtdec_prepare_fdt()); 331 return 0; 332 } 333 334 /* 335 * This function is a little odd in that it accesses global data. At some 336 * point if the architecture board.c files merge this will make more sense. 337 * Even now, it is common code. 338 */ 339 int fdtdec_prepare_fdt(void) 340 { 341 if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) || 342 fdt_check_header(gd->fdt_blob)) { 343 printf("No valid FDT found - please append one to U-Boot " 344 "binary, use u-boot-dtb.bin or define " 345 "CONFIG_OF_EMBED. For sandbox, use -d <file.dtb>\n"); 346 return -1; 347 } 348 return 0; 349 } 350 351 int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name) 352 { 353 const u32 *phandle; 354 int lookup; 355 356 debug("%s: %s\n", __func__, prop_name); 357 phandle = fdt_getprop(blob, node, prop_name, NULL); 358 if (!phandle) 359 return -FDT_ERR_NOTFOUND; 360 361 lookup = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*phandle)); 362 return lookup; 363 } 364 365 /** 366 * Look up a property in a node and check that it has a minimum length. 367 * 368 * @param blob FDT blob 369 * @param node node to examine 370 * @param prop_name name of property to find 371 * @param min_len minimum property length in bytes 372 * @param err 0 if ok, or -FDT_ERR_NOTFOUND if the property is not 373 found, or -FDT_ERR_BADLAYOUT if not enough data 374 * @return pointer to cell, which is only valid if err == 0 375 */ 376 static const void *get_prop_check_min_len(const void *blob, int node, 377 const char *prop_name, int min_len, int *err) 378 { 379 const void *cell; 380 int len; 381 382 debug("%s: %s\n", __func__, prop_name); 383 cell = fdt_getprop(blob, node, prop_name, &len); 384 if (!cell) 385 *err = -FDT_ERR_NOTFOUND; 386 else if (len < min_len) 387 *err = -FDT_ERR_BADLAYOUT; 388 else 389 *err = 0; 390 return cell; 391 } 392 393 int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, 394 u32 *array, int count) 395 { 396 const u32 *cell; 397 int i, err = 0; 398 399 debug("%s: %s\n", __func__, prop_name); 400 cell = get_prop_check_min_len(blob, node, prop_name, 401 sizeof(u32) * count, &err); 402 if (!err) { 403 for (i = 0; i < count; i++) 404 array[i] = fdt32_to_cpu(cell[i]); 405 } 406 return err; 407 } 408 409 const u32 *fdtdec_locate_array(const void *blob, int node, 410 const char *prop_name, int count) 411 { 412 const u32 *cell; 413 int err; 414 415 cell = get_prop_check_min_len(blob, node, prop_name, 416 sizeof(u32) * count, &err); 417 return err ? NULL : cell; 418 } 419 420 int fdtdec_get_bool(const void *blob, int node, const char *prop_name) 421 { 422 const s32 *cell; 423 int len; 424 425 debug("%s: %s\n", __func__, prop_name); 426 cell = fdt_getprop(blob, node, prop_name, &len); 427 return cell != NULL; 428 } 429 430 /** 431 * Decode a list of GPIOs from an FDT. This creates a list of GPIOs with no 432 * terminating item. 433 * 434 * @param blob FDT blob to use 435 * @param node Node to look at 436 * @param prop_name Node property name 437 * @param gpio Array of gpio elements to fill from FDT. This will be 438 * untouched if either 0 or an error is returned 439 * @param max_count Maximum number of elements allowed 440 * @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would 441 * be exceeded, or -FDT_ERR_NOTFOUND if the property is missing. 442 */ 443 int fdtdec_decode_gpios(const void *blob, int node, const char *prop_name, 444 struct fdt_gpio_state *gpio, int max_count) 445 { 446 const struct fdt_property *prop; 447 const u32 *cell; 448 const char *name; 449 int len, i; 450 451 debug("%s: %s\n", __func__, prop_name); 452 assert(max_count > 0); 453 prop = fdt_get_property(blob, node, prop_name, &len); 454 if (!prop) { 455 debug("%s: property '%s' missing\n", __func__, prop_name); 456 return -FDT_ERR_NOTFOUND; 457 } 458 459 /* We will use the name to tag the GPIO */ 460 name = fdt_string(blob, fdt32_to_cpu(prop->nameoff)); 461 cell = (u32 *)prop->data; 462 len /= sizeof(u32) * 3; /* 3 cells per GPIO record */ 463 if (len > max_count) { 464 debug(" %s: too many GPIOs / cells for " 465 "property '%s'\n", __func__, prop_name); 466 return -FDT_ERR_BADLAYOUT; 467 } 468 469 /* Read out the GPIO data from the cells */ 470 for (i = 0; i < len; i++, cell += 3) { 471 gpio[i].gpio = fdt32_to_cpu(cell[1]); 472 gpio[i].flags = fdt32_to_cpu(cell[2]); 473 gpio[i].name = name; 474 } 475 476 return len; 477 } 478 479 int fdtdec_decode_gpio(const void *blob, int node, const char *prop_name, 480 struct fdt_gpio_state *gpio) 481 { 482 int err; 483 484 debug("%s: %s\n", __func__, prop_name); 485 gpio->gpio = FDT_GPIO_NONE; 486 gpio->name = NULL; 487 err = fdtdec_decode_gpios(blob, node, prop_name, gpio, 1); 488 return err == 1 ? 0 : err; 489 } 490 491 int fdtdec_get_gpio(struct fdt_gpio_state *gpio) 492 { 493 int val; 494 495 if (!fdt_gpio_isvalid(gpio)) 496 return -1; 497 498 val = gpio_get_value(gpio->gpio); 499 return gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val; 500 } 501 502 int fdtdec_set_gpio(struct fdt_gpio_state *gpio, int val) 503 { 504 if (!fdt_gpio_isvalid(gpio)) 505 return -1; 506 507 val = gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val; 508 return gpio_set_value(gpio->gpio, val); 509 } 510 511 int fdtdec_setup_gpio(struct fdt_gpio_state *gpio) 512 { 513 /* 514 * Return success if there is no GPIO defined. This is used for 515 * optional GPIOs) 516 */ 517 if (!fdt_gpio_isvalid(gpio)) 518 return 0; 519 520 if (gpio_request(gpio->gpio, gpio->name)) 521 return -1; 522 return 0; 523 } 524 525 int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name, 526 u8 *array, int count) 527 { 528 const u8 *cell; 529 int err; 530 531 cell = get_prop_check_min_len(blob, node, prop_name, count, &err); 532 if (!err) 533 memcpy(array, cell, count); 534 return err; 535 } 536 537 const u8 *fdtdec_locate_byte_array(const void *blob, int node, 538 const char *prop_name, int count) 539 { 540 const u8 *cell; 541 int err; 542 543 cell = get_prop_check_min_len(blob, node, prop_name, count, &err); 544 if (err) 545 return NULL; 546 return cell; 547 } 548 549 int fdtdec_get_config_int(const void *blob, const char *prop_name, 550 int default_val) 551 { 552 int config_node; 553 554 debug("%s: %s\n", __func__, prop_name); 555 config_node = fdt_path_offset(blob, "/config"); 556 if (config_node < 0) 557 return default_val; 558 return fdtdec_get_int(blob, config_node, prop_name, default_val); 559 } 560 561 int fdtdec_get_config_bool(const void *blob, const char *prop_name) 562 { 563 int config_node; 564 const void *prop; 565 566 debug("%s: %s\n", __func__, prop_name); 567 config_node = fdt_path_offset(blob, "/config"); 568 if (config_node < 0) 569 return 0; 570 prop = fdt_get_property(blob, config_node, prop_name, NULL); 571 572 return prop != NULL; 573 } 574 575 char *fdtdec_get_config_string(const void *blob, const char *prop_name) 576 { 577 const char *nodep; 578 int nodeoffset; 579 int len; 580 581 debug("%s: %s\n", __func__, prop_name); 582 nodeoffset = fdt_path_offset(blob, "/config"); 583 if (nodeoffset < 0) 584 return NULL; 585 586 nodep = fdt_getprop(blob, nodeoffset, prop_name, &len); 587 if (!nodep) 588 return NULL; 589 590 return (char *)nodep; 591 } 592 593 int fdtdec_decode_region(const void *blob, int node, 594 const char *prop_name, void **ptrp, size_t *size) 595 { 596 const fdt_addr_t *cell; 597 int len; 598 599 debug("%s: %s\n", __func__, prop_name); 600 cell = fdt_getprop(blob, node, prop_name, &len); 601 if (!cell || (len != sizeof(fdt_addr_t) * 2)) 602 return -1; 603 604 *ptrp = map_sysmem(fdt_addr_to_cpu(*cell), *size); 605 *size = fdt_size_to_cpu(cell[1]); 606 debug("%s: size=%zx\n", __func__, *size); 607 return 0; 608 } 609 610 /** 611 * Read a flash entry from the fdt 612 * 613 * @param blob FDT blob 614 * @param node Offset of node to read 615 * @param name Name of node being read 616 * @param entry Place to put offset and size of this node 617 * @return 0 if ok, -ve on error 618 */ 619 int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, 620 struct fmap_entry *entry) 621 { 622 u32 reg[2]; 623 624 if (fdtdec_get_int_array(blob, node, "reg", reg, 2)) { 625 debug("Node '%s' has bad/missing 'reg' property\n", name); 626 return -FDT_ERR_NOTFOUND; 627 } 628 entry->offset = reg[0]; 629 entry->length = reg[1]; 630 631 return 0; 632 } 633 #endif 634