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