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