1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 2 * 3 * Copyright 2010-2016 Freescale Semiconductor Inc. 4 * Copyright 2017 NXP 5 * 6 */ 7 8 #include <dpaa_of.h> 9 #include <assert.h> 10 #include <rte_string_fns.h> 11 #include <dpaax_logs.h> 12 13 static int alive; 14 static struct dt_dir root_dir; 15 static const char *base_dir; 16 static COMPAT_LIST_HEAD(linear); 17 18 static int 19 of_open_dir(const char *relative_path, struct dirent ***d) 20 { 21 int ret; 22 char full_path[PATH_MAX]; 23 24 snprintf(full_path, PATH_MAX, "%s/%s", base_dir, relative_path); 25 ret = scandir(full_path, d, 0, versionsort); 26 if (ret < 0) 27 DPAAX_LOG(ERR, "Failed to open directory %s", 28 full_path); 29 return ret; 30 } 31 32 static void 33 of_close_dir(struct dirent **d, int num) 34 { 35 while (num--) 36 free(d[num]); 37 free(d); 38 } 39 40 static int 41 of_open_file(const char *relative_path) 42 { 43 int ret; 44 char full_path[PATH_MAX]; 45 46 snprintf(full_path, PATH_MAX, "%s/%s", base_dir, relative_path); 47 ret = open(full_path, O_RDONLY); 48 if (ret < 0) 49 DPAAX_LOG(ERR, "Failed to open directory %s", 50 full_path); 51 return ret; 52 } 53 54 static void 55 process_file(struct dirent *dent, struct dt_dir *parent) 56 { 57 int fd; 58 struct dt_file *f = malloc(sizeof(*f)); 59 60 if (!f) { 61 DPAAX_LOG(DEBUG, "Unable to allocate memory for file node"); 62 return; 63 } 64 f->node.is_file = 1; 65 strlcpy(f->node.node.name, dent->d_name, NAME_MAX); 66 snprintf(f->node.node.full_name, PATH_MAX, "%s/%s", 67 parent->node.node.full_name, dent->d_name); 68 f->parent = parent; 69 fd = of_open_file(f->node.node.full_name); 70 if (fd < 0) { 71 DPAAX_LOG(DEBUG, "Unable to open file node"); 72 free(f); 73 return; 74 } 75 f->len = read(fd, f->buf, OF_FILE_BUF_MAX); 76 close(fd); 77 if (f->len < 0) { 78 DPAAX_LOG(DEBUG, "Unable to read file node"); 79 free(f); 80 return; 81 } 82 list_add_tail(&f->node.list, &parent->files); 83 } 84 85 static const struct dt_dir * 86 node2dir(const struct device_node *n) 87 { 88 struct dt_node *dn = container_of((struct device_node *)n, 89 struct dt_node, node); 90 const struct dt_dir *d = container_of(dn, struct dt_dir, node); 91 92 assert(!dn->is_file); 93 return d; 94 } 95 96 /* process_dir() calls iterate_dir(), but the latter will also call the former 97 * when recursing into sub-directories, so a predeclaration is needed. 98 */ 99 static int process_dir(const char *relative_path, struct dt_dir *dt); 100 101 static int 102 iterate_dir(struct dirent **d, int num, struct dt_dir *dt) 103 { 104 int loop; 105 /* Iterate the directory contents */ 106 for (loop = 0; loop < num; loop++) { 107 struct dt_dir *subdir; 108 int ret; 109 /* Ignore dot files of all types (especially "..") */ 110 if (d[loop]->d_name[0] == '.') 111 continue; 112 switch (d[loop]->d_type) { 113 case DT_REG: 114 process_file(d[loop], dt); 115 break; 116 case DT_DIR: 117 subdir = malloc(sizeof(*subdir)); 118 if (!subdir) { 119 perror("malloc"); 120 return -ENOMEM; 121 } 122 strlcpy(subdir->node.node.name, d[loop]->d_name, 123 NAME_MAX); 124 snprintf(subdir->node.node.full_name, PATH_MAX, 125 "%s/%s", dt->node.node.full_name, 126 d[loop]->d_name); 127 subdir->parent = dt; 128 ret = process_dir(subdir->node.node.full_name, subdir); 129 if (ret) 130 return ret; 131 list_add_tail(&subdir->node.list, &dt->subdirs); 132 break; 133 default: 134 DPAAX_LOG(DEBUG, "Ignoring invalid dt entry %s/%s", 135 dt->node.node.full_name, d[loop]->d_name); 136 } 137 } 138 return 0; 139 } 140 141 static int 142 process_dir(const char *relative_path, struct dt_dir *dt) 143 { 144 struct dirent **d; 145 int ret, num; 146 147 dt->node.is_file = 0; 148 INIT_LIST_HEAD(&dt->subdirs); 149 INIT_LIST_HEAD(&dt->files); 150 ret = of_open_dir(relative_path, &d); 151 if (ret < 0) 152 return ret; 153 num = ret; 154 ret = iterate_dir(d, num, dt); 155 of_close_dir(d, num); 156 return (ret < 0) ? ret : 0; 157 } 158 159 static void 160 linear_dir(struct dt_dir *d) 161 { 162 struct dt_file *f; 163 struct dt_dir *dd; 164 165 d->compatible = NULL; 166 d->status = NULL; 167 d->lphandle = NULL; 168 d->a_cells = NULL; 169 d->s_cells = NULL; 170 d->reg = NULL; 171 list_for_each_entry(f, &d->files, node.list) { 172 if (!strcmp(f->node.node.name, "compatible")) { 173 if (d->compatible) 174 DPAAX_LOG(DEBUG, "Duplicate compatible in" 175 " %s", d->node.node.full_name); 176 d->compatible = f; 177 } else if (!strcmp(f->node.node.name, "status")) { 178 if (d->status) 179 DPAAX_LOG(DEBUG, "Duplicate status in %s", 180 d->node.node.full_name); 181 d->status = f; 182 } else if (!strcmp(f->node.node.name, "linux,phandle")) { 183 if (d->lphandle) 184 DPAAX_LOG(DEBUG, "Duplicate lphandle in %s", 185 d->node.node.full_name); 186 d->lphandle = f; 187 } else if (!strcmp(f->node.node.name, "phandle")) { 188 if (d->lphandle) 189 DPAAX_LOG(DEBUG, "Duplicate lphandle in %s", 190 d->node.node.full_name); 191 d->lphandle = f; 192 } else if (!strcmp(f->node.node.name, "#address-cells")) { 193 if (d->a_cells) 194 DPAAX_LOG(DEBUG, "Duplicate a_cells in %s", 195 d->node.node.full_name); 196 d->a_cells = f; 197 } else if (!strcmp(f->node.node.name, "#size-cells")) { 198 if (d->s_cells) 199 DPAAX_LOG(DEBUG, "Duplicate s_cells in %s", 200 d->node.node.full_name); 201 d->s_cells = f; 202 } else if (!strcmp(f->node.node.name, "reg")) { 203 if (d->reg) 204 DPAAX_LOG(DEBUG, "Duplicate reg in %s", 205 d->node.node.full_name); 206 d->reg = f; 207 } 208 } 209 210 list_for_each_entry(dd, &d->subdirs, node.list) { 211 list_add_tail(&dd->linear, &linear); 212 linear_dir(dd); 213 } 214 } 215 216 int 217 of_init_path(const char *dt_path) 218 { 219 int ret; 220 221 base_dir = dt_path; 222 223 /* This needs to be singleton initialization */ 224 DPAAX_HWWARN(alive, "Double-init of device-tree driver!"); 225 226 /* Prepare root node (the remaining fields are set in process_dir()) */ 227 root_dir.node.node.name[0] = '\0'; 228 root_dir.node.node.full_name[0] = '\0'; 229 INIT_LIST_HEAD(&root_dir.node.list); 230 root_dir.parent = NULL; 231 232 /* Kick things off... */ 233 ret = process_dir("", &root_dir); 234 if (ret) { 235 DPAAX_LOG(ERR, "Unable to parse device tree"); 236 return ret; 237 } 238 239 /* Now make a flat, linear list of directories */ 240 linear_dir(&root_dir); 241 alive = 1; 242 return 0; 243 } 244 245 static void 246 destroy_dir(struct dt_dir *d) 247 { 248 struct dt_file *f, *tmpf; 249 struct dt_dir *dd, *tmpd; 250 251 list_for_each_entry_safe(f, tmpf, &d->files, node.list) { 252 list_del(&f->node.list); 253 free(f); 254 } 255 list_for_each_entry_safe(dd, tmpd, &d->subdirs, node.list) { 256 destroy_dir(dd); 257 list_del(&dd->node.list); 258 free(dd); 259 } 260 } 261 262 void 263 of_finish(void) 264 { 265 DPAAX_HWWARN(!alive, "Double-finish of device-tree driver!"); 266 267 destroy_dir(&root_dir); 268 INIT_LIST_HEAD(&linear); 269 alive = 0; 270 } 271 272 static const struct dt_dir * 273 next_linear(const struct dt_dir *f) 274 { 275 if (f->linear.next == &linear) 276 return NULL; 277 return list_entry(f->linear.next, struct dt_dir, linear); 278 } 279 280 static int 281 check_compatible(const struct dt_file *f, const char *compatible) 282 { 283 const char *c = (char *)f->buf; 284 unsigned int len, remains = f->len; 285 286 while (remains) { 287 len = strlen(c); 288 if (!strcmp(c, compatible)) 289 return 1; 290 291 if (remains < len + 1) 292 break; 293 294 c += (len + 1); 295 remains -= (len + 1); 296 } 297 return 0; 298 } 299 300 const struct device_node * 301 of_find_compatible_node(const struct device_node *from, 302 const char *type __rte_unused, 303 const char *compatible) 304 { 305 const struct dt_dir *d; 306 307 DPAAX_HWWARN(!alive, "Device-tree driver not initialised!"); 308 309 if (list_empty(&linear)) 310 return NULL; 311 if (!from) 312 d = list_entry(linear.next, struct dt_dir, linear); 313 else 314 d = node2dir(from); 315 for (d = next_linear(d); d && (!d->compatible || 316 !check_compatible(d->compatible, 317 compatible)); 318 d = next_linear(d)) 319 ; 320 if (d) 321 return &d->node.node; 322 return NULL; 323 } 324 325 const void * 326 of_get_property(const struct device_node *from, const char *name, 327 size_t *lenp) 328 { 329 const struct dt_dir *d; 330 const struct dt_file *f; 331 332 DPAAX_HWWARN(!alive, "Device-tree driver not initialised!"); 333 334 d = node2dir(from); 335 list_for_each_entry(f, &d->files, node.list) 336 if (!strcmp(f->node.node.name, name)) { 337 if (lenp) 338 *lenp = f->len; 339 return f->buf; 340 } 341 return NULL; 342 } 343 344 bool 345 of_device_is_available(const struct device_node *dev_node) 346 { 347 const struct dt_dir *d; 348 349 DPAAX_HWWARN(!alive, "Device-tree driver not initialised!"); 350 d = node2dir(dev_node); 351 if (!d->status) 352 return true; 353 if (!strcmp((char *)d->status->buf, "okay")) 354 return true; 355 if (!strcmp((char *)d->status->buf, "ok")) 356 return true; 357 return false; 358 } 359 360 const struct device_node * 361 of_find_node_by_phandle(uint64_t ph) 362 { 363 const struct dt_dir *d; 364 365 DPAAX_HWWARN(!alive, "Device-tree driver not initialised!"); 366 list_for_each_entry(d, &linear, linear) 367 if (d->lphandle && (d->lphandle->len == 4) && 368 !memcmp(d->lphandle->buf, &ph, 4)) 369 return &d->node.node; 370 return NULL; 371 } 372 373 const struct device_node * 374 of_get_parent(const struct device_node *dev_node) 375 { 376 const struct dt_dir *d; 377 378 DPAAX_HWWARN(!alive, "Device-tree driver not initialised!"); 379 380 if (!dev_node) 381 return NULL; 382 d = node2dir(dev_node); 383 if (!d->parent) 384 return NULL; 385 return &d->parent->node.node; 386 } 387 388 const struct device_node * 389 of_get_next_child(const struct device_node *dev_node, 390 const struct device_node *prev) 391 { 392 const struct dt_dir *p, *c; 393 394 DPAAX_HWWARN(!alive, "Device-tree driver not initialised!"); 395 396 if (!dev_node) 397 return NULL; 398 p = node2dir(dev_node); 399 if (prev) { 400 c = node2dir(prev); 401 DPAAX_HWWARN((c->parent != p), "Parent/child mismatch"); 402 if (c->parent != p) 403 return NULL; 404 if (c->node.list.next == &p->subdirs) 405 /* prev was the last child */ 406 return NULL; 407 c = list_entry(c->node.list.next, struct dt_dir, node.list); 408 return &c->node.node; 409 } 410 /* Return first child */ 411 if (list_empty(&p->subdirs)) 412 return NULL; 413 c = list_entry(p->subdirs.next, struct dt_dir, node.list); 414 return &c->node.node; 415 } 416 417 uint32_t 418 of_n_addr_cells(const struct device_node *dev_node) 419 { 420 const struct dt_dir *d; 421 422 DPAAX_HWWARN(!alive, "Device-tree driver not initialised"); 423 if (!dev_node) 424 return OF_DEFAULT_NA; 425 d = node2dir(dev_node); 426 while ((d = d->parent)) 427 if (d->a_cells) { 428 unsigned char *buf = 429 (unsigned char *)&d->a_cells->buf[0]; 430 assert(d->a_cells->len == 4); 431 return ((uint32_t)buf[0] << 24) | 432 ((uint32_t)buf[1] << 16) | 433 ((uint32_t)buf[2] << 8) | 434 (uint32_t)buf[3]; 435 } 436 return OF_DEFAULT_NA; 437 } 438 439 uint32_t 440 of_n_size_cells(const struct device_node *dev_node) 441 { 442 const struct dt_dir *d; 443 444 DPAAX_HWWARN(!alive, "Device-tree driver not initialised!"); 445 if (!dev_node) 446 return OF_DEFAULT_NA; 447 d = node2dir(dev_node); 448 while ((d = d->parent)) 449 if (d->s_cells) { 450 unsigned char *buf = 451 (unsigned char *)&d->s_cells->buf[0]; 452 assert(d->s_cells->len == 4); 453 return ((uint32_t)buf[0] << 24) | 454 ((uint32_t)buf[1] << 16) | 455 ((uint32_t)buf[2] << 8) | 456 (uint32_t)buf[3]; 457 } 458 return OF_DEFAULT_NS; 459 } 460 461 const uint32_t * 462 of_get_address(const struct device_node *dev_node, size_t idx, 463 uint64_t *size, uint32_t *flags __rte_unused) 464 { 465 const struct dt_dir *d; 466 const unsigned char *buf; 467 uint32_t na = of_n_addr_cells(dev_node); 468 uint32_t ns = of_n_size_cells(dev_node); 469 470 if (!dev_node) 471 d = &root_dir; 472 else 473 d = node2dir(dev_node); 474 if (!d->reg) 475 return NULL; 476 assert(d->reg->len % ((na + ns) * 4) == 0); 477 assert(d->reg->len / ((na + ns) * 4) > (unsigned int) idx); 478 buf = (const unsigned char *)&d->reg->buf[0]; 479 buf += (na + ns) * idx * 4; 480 if (size) 481 for (*size = 0; ns > 0; ns--, na++) 482 *size = (*size << 32) + 483 (((uint32_t)buf[4 * na] << 24) | 484 ((uint32_t)buf[4 * na + 1] << 16) | 485 ((uint32_t)buf[4 * na + 2] << 8) | 486 (uint32_t)buf[4 * na + 3]); 487 return (const uint32_t *)buf; 488 } 489 490 uint64_t 491 of_translate_address(const struct device_node *dev_node, 492 const uint32_t *addr) 493 { 494 uint64_t phys_addr, tmp_addr; 495 const struct device_node *parent; 496 const uint32_t *ranges; 497 size_t rlen; 498 uint32_t na, pna; 499 500 DPAAX_HWWARN(!alive, "Device-tree driver not initialised!"); 501 assert(dev_node != NULL); 502 503 na = of_n_addr_cells(dev_node); 504 phys_addr = of_read_number(addr, na); 505 506 dev_node = of_get_parent(dev_node); 507 if (!dev_node) 508 return 0; 509 else if (node2dir(dev_node) == &root_dir) 510 return phys_addr; 511 512 do { 513 pna = of_n_addr_cells(dev_node); 514 parent = of_get_parent(dev_node); 515 if (!parent) 516 return 0; 517 518 ranges = of_get_property(dev_node, "ranges", &rlen); 519 /* "ranges" property is missing. Translation breaks */ 520 if (!ranges) 521 return 0; 522 /* "ranges" property is empty. Do 1:1 translation */ 523 else if (rlen == 0) 524 continue; 525 else 526 tmp_addr = of_read_number(ranges + na, pna); 527 528 na = pna; 529 dev_node = parent; 530 phys_addr += tmp_addr; 531 } while (node2dir(parent) != &root_dir); 532 533 return phys_addr; 534 } 535 536 bool 537 of_device_is_compatible(const struct device_node *dev_node, 538 const char *compatible) 539 { 540 const struct dt_dir *d; 541 542 DPAAX_HWWARN(!alive, "Device-tree driver not initialised!"); 543 if (!dev_node) 544 d = &root_dir; 545 else 546 d = node2dir(dev_node); 547 if (d->compatible && check_compatible(d->compatible, compatible)) 548 return true; 549 return false; 550 } 551 552 static const void *of_get_mac_addr(const struct device_node *np, 553 const char *name) 554 { 555 return of_get_property(np, name, NULL); 556 } 557 558 /** 559 * Search the device tree for the best MAC address to use. 'mac-address' is 560 * checked first, because that is supposed to contain to "most recent" MAC 561 * address. If that isn't set, then 'local-mac-address' is checked next, 562 * because that is the default address. If that isn't set, then the obsolete 563 * 'address' is checked, just in case we're using an old device tree. 564 * 565 * Note that the 'address' property is supposed to contain a virtual address of 566 * the register set, but some DTS files have redefined that property to be the 567 * MAC address. 568 * 569 * All-zero MAC addresses are rejected, because those could be properties that 570 * exist in the device tree, but were not set by U-Boot. For example, the 571 * DTS could define 'mac-address' and 'local-mac-address', with zero MAC 572 * addresses. Some older U-Boots only initialized 'local-mac-address'. In 573 * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists 574 * but is all zeros. 575 */ 576 const void *of_get_mac_address(const struct device_node *np) 577 { 578 const void *addr; 579 580 addr = of_get_mac_addr(np, "mac-address"); 581 if (addr) 582 return addr; 583 584 addr = of_get_mac_addr(np, "local-mac-address"); 585 if (addr) 586 return addr; 587 588 return of_get_mac_addr(np, "address"); 589 } 590