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