1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2021, Linaro Limited 4 * Copyright (c) 2021, Bootlin 5 * Copyright (c) 2021, Linaro Limited 6 * Copyright (c) 2021, STMicroelectronics 7 */ 8 9 #include <assert.h> 10 #include <config.h> 11 #include <initcall.h> 12 #include <kernel/boot.h> 13 #include <kernel/dt.h> 14 #include <kernel/dt_driver.h> 15 #include <libfdt.h> 16 #include <malloc.h> 17 #include <sys/queue.h> 18 #include <tee_api_defines_extensions.h> 19 #include <tee_api_types.h> 20 21 /* 22 * struct dt_driver_probe - Node instance in secure FDT to probe a driver for 23 * 24 * @link: List hook 25 * @nodeoffset: Node offset of device referenced in the FDT 26 * @type: One of DT_DRIVER_* or DT_DRIVER_NOTYPE. 27 * @deferrals: Driver probe deferrals count 28 * @dt_drv: Matching driver to probe if found or NULL 29 * @dm: Matching reference if applicable or NULL 30 */ 31 struct dt_driver_probe { 32 int nodeoffset; 33 enum dt_driver_type type; 34 unsigned int deferrals; 35 const struct dt_driver *dt_drv; 36 const struct dt_device_match *dm; 37 TAILQ_ENTRY(dt_driver_probe) link; 38 }; 39 40 /* 41 * struct dt_driver_provider - DT related info on probed device 42 * 43 * Saves information on the probed device so that device 44 * drivers can get resources from DT phandle and related arguments. 45 * 46 * @nodeoffset: Node offset of device referenced in the FDT 47 * @type: One of DT_DRIVER_* or DT_DRIVER_NOTYPE. 48 * @provider_cells: Cells count in the FDT used by the driver's references 49 * @get_of_device: Function to get driver's device ref from phandle data 50 * @priv_data: Driver private data passed as @get_of_device argument 51 * @link: Reference in DT driver providers list 52 */ 53 struct dt_driver_provider { 54 int nodeoffset; 55 enum dt_driver_type type; 56 unsigned int provider_cells; 57 uint32_t phandle; 58 get_of_device_func get_of_device; 59 void *priv_data; 60 SLIST_ENTRY(dt_driver_provider) link; 61 }; 62 63 /* 64 * Device driver providers are able to provide a driver specific instance 65 * related to device phandle arguments found in the secure embedded FDT. 66 */ 67 static SLIST_HEAD(, dt_driver_provider) dt_driver_provider_list = 68 SLIST_HEAD_INITIALIZER(dt_driver_provider_list); 69 70 /* FDT nodes for which a matching driver is to be probed */ 71 static TAILQ_HEAD(dt_driver_probe_head, dt_driver_probe) dt_driver_probe_list = 72 TAILQ_HEAD_INITIALIZER(dt_driver_probe_list); 73 74 /* FDT nodes for which a matching driver has been successfully probed */ 75 static TAILQ_HEAD(, dt_driver_probe) dt_driver_ready_list = 76 TAILQ_HEAD_INITIALIZER(dt_driver_ready_list); 77 78 /* List of the nodes for which a compatible driver but reported a failure */ 79 static TAILQ_HEAD(, dt_driver_probe) dt_driver_failed_list = 80 TAILQ_HEAD_INITIALIZER(dt_driver_failed_list); 81 82 /* Flag enabled when a new node (possibly typed) is added in the probe list */ 83 static bool added_node; 84 85 /* Resolve drivers dependencies on core crypto layer */ 86 static bool tee_crypt_is_ready; 87 88 void dt_driver_crypt_init_complete(void) 89 { 90 assert(!tee_crypt_is_ready); 91 tee_crypt_is_ready = true; 92 } 93 94 TEE_Result dt_driver_get_crypto(void) 95 { 96 if (tee_crypt_is_ready) 97 return TEE_SUCCESS; 98 else 99 return TEE_ERROR_DEFER_DRIVER_INIT; 100 } 101 102 static void assert_type_is_valid(enum dt_driver_type type) 103 { 104 switch (type) { 105 case DT_DRIVER_NOTYPE: 106 case DT_DRIVER_CLK: 107 case DT_DRIVER_RSTCTRL: 108 case DT_DRIVER_UART: 109 return; 110 default: 111 assert(0); 112 } 113 } 114 115 /* 116 * Driver provider registering API functions 117 */ 118 119 TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset, 120 get_of_device_func get_of_device, 121 void *priv, enum dt_driver_type type) 122 { 123 struct dt_driver_provider *prv = NULL; 124 int provider_cells = 0; 125 uint32_t phandle = 0; 126 127 assert_type_is_valid(type); 128 129 provider_cells = fdt_get_dt_driver_cells(fdt, nodeoffset, type); 130 if (provider_cells < 0) { 131 DMSG("Failed to find provider cells: %d", provider_cells); 132 return TEE_ERROR_GENERIC; 133 } 134 135 phandle = fdt_get_phandle(fdt, nodeoffset); 136 if (phandle == (uint32_t)-1) { 137 DMSG("Failed to find provide phandle"); 138 return TEE_ERROR_GENERIC; 139 } 140 141 prv = calloc(1, sizeof(*prv)); 142 if (!prv) 143 return TEE_ERROR_OUT_OF_MEMORY; 144 145 prv->nodeoffset = nodeoffset; 146 prv->type = type; 147 prv->provider_cells = provider_cells; 148 prv->phandle = phandle; 149 prv->get_of_device = get_of_device; 150 prv->priv_data = priv; 151 152 SLIST_INSERT_HEAD(&dt_driver_provider_list, prv, link); 153 154 return TEE_SUCCESS; 155 } 156 157 /* 158 * Helper functions for dt_drivers querying driver provider information 159 */ 160 161 int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset, 162 enum dt_driver_type type) 163 { 164 const char *cells_name = NULL; 165 const fdt32_t *c = NULL; 166 int len = 0; 167 168 switch (type) { 169 case DT_DRIVER_CLK: 170 cells_name = "#clock-cells"; 171 break; 172 case DT_DRIVER_RSTCTRL: 173 cells_name = "#reset-cells"; 174 break; 175 default: 176 panic(); 177 } 178 179 c = fdt_getprop(fdt, nodeoffset, cells_name, &len); 180 if (!c) 181 return len; 182 183 if (len != sizeof(*c)) 184 return -FDT_ERR_BADNCELLS; 185 186 return fdt32_to_cpu(*c); 187 } 188 189 unsigned int dt_driver_provider_cells(struct dt_driver_provider *prv) 190 { 191 return prv->provider_cells; 192 } 193 194 struct dt_driver_provider * 195 dt_driver_get_provider_by_node(int nodeoffset, enum dt_driver_type type) 196 { 197 struct dt_driver_provider *prv = NULL; 198 199 SLIST_FOREACH(prv, &dt_driver_provider_list, link) 200 if (prv->nodeoffset == nodeoffset && prv->type == type) 201 return prv; 202 203 return NULL; 204 } 205 206 struct dt_driver_provider * 207 dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type) 208 { 209 struct dt_driver_provider *prv = NULL; 210 211 SLIST_FOREACH(prv, &dt_driver_provider_list, link) 212 if (prv->phandle == phandle && prv->type == type) 213 return prv; 214 215 return NULL; 216 } 217 218 static void *device_from_provider_prop(struct dt_driver_provider *prv, 219 const void *fdt, int phandle_node, 220 const uint32_t *prop, TEE_Result *res) 221 { 222 struct dt_driver_phandle_args *pargs = NULL; 223 unsigned int n = 0; 224 void *device = NULL; 225 226 pargs = calloc(1, prv->provider_cells * sizeof(uint32_t *) + 227 sizeof(*pargs)); 228 if (!pargs) { 229 *res = TEE_ERROR_OUT_OF_MEMORY; 230 return NULL; 231 } 232 233 pargs->fdt = fdt; 234 pargs->phandle_node = phandle_node; 235 pargs->args_count = prv->provider_cells; 236 for (n = 0; n < prv->provider_cells; n++) 237 pargs->args[n] = fdt32_to_cpu(prop[n + 1]); 238 239 device = prv->get_of_device(pargs, prv->priv_data, res); 240 241 free(pargs); 242 243 return device; 244 } 245 246 void *dt_driver_device_from_node_idx_prop(const char *prop_name, 247 const void *fdt, int nodeoffset, 248 unsigned int prop_idx, 249 enum dt_driver_type type, 250 TEE_Result *res) 251 { 252 int len = 0; 253 int idx = 0; 254 int idx32 = 0; 255 int prv_cells = 0; 256 int phandle_node = -1; 257 uint32_t phandle = 0; 258 const uint32_t *prop = NULL; 259 struct dt_driver_provider *prv = NULL; 260 261 prop = fdt_getprop(fdt, nodeoffset, prop_name, &len); 262 if (!prop) { 263 DMSG("Property %s missing in node %s", prop_name, 264 fdt_get_name(fdt, nodeoffset, NULL)); 265 *res = TEE_ERROR_ITEM_NOT_FOUND; 266 return NULL; 267 } 268 269 while (idx < len) { 270 idx32 = idx / sizeof(uint32_t); 271 phandle = fdt32_to_cpu(prop[idx32]); 272 if (!phandle) { 273 if (!prop_idx) 274 break; 275 idx += sizeof(phandle); 276 prop_idx--; 277 continue; 278 } 279 280 prv = dt_driver_get_provider_by_phandle(phandle, type); 281 if (!prv) { 282 /* No provider registered yet */ 283 *res = TEE_ERROR_DEFER_DRIVER_INIT; 284 return NULL; 285 } 286 287 prv_cells = dt_driver_provider_cells(prv); 288 if (prop_idx) { 289 prop_idx--; 290 idx += sizeof(phandle) + prv_cells * sizeof(uint32_t); 291 continue; 292 } 293 294 return device_from_provider_prop(prv, fdt, phandle_node, 295 prop + idx32, res); 296 } 297 298 *res = TEE_ERROR_ITEM_NOT_FOUND; 299 return NULL; 300 } 301 302 static void __maybe_unused print_probe_list(const void *fdt __maybe_unused) 303 { 304 struct dt_driver_probe *elt = NULL; 305 unsigned int count = 0; 306 307 TAILQ_FOREACH(elt, &dt_driver_probe_list, link) 308 count++; 309 310 DMSG("Probe list: %u elements", count); 311 TAILQ_FOREACH(elt, &dt_driver_probe_list, link) 312 DMSG("|- Driver %s probes on node %s", 313 elt->dt_drv->name, 314 fdt_get_name(fdt, elt->nodeoffset, NULL)); 315 316 DMSG("`- Probe list end"); 317 318 count = 0; 319 TAILQ_FOREACH(elt, &dt_driver_failed_list, link) 320 count++; 321 322 DMSG("Failed list: %u elements", count); 323 TAILQ_FOREACH(elt, &dt_driver_failed_list, link) 324 EMSG("|- Driver %s on node %s failed", elt->dt_drv->name, 325 fdt_get_name(fdt, elt->nodeoffset, NULL)); 326 327 DMSG("`- Failed list end"); 328 } 329 330 /* 331 * Probe element: push to ready list if succeeds, push to probe list if probe 332 * if deferred, panic with an error trace otherwise. 333 */ 334 static TEE_Result probe_driver_node(const void *fdt, 335 struct dt_driver_probe *elt) 336 { 337 TEE_Result res = TEE_ERROR_GENERIC; 338 const char __maybe_unused *drv_name = NULL; 339 const char __maybe_unused *node_name = NULL; 340 341 node_name = fdt_get_name(fdt, elt->nodeoffset, NULL); 342 drv_name = elt->dt_drv->name; 343 344 if (!elt->dt_drv->probe) { 345 DMSG("No probe operator for driver %s, skipped", drv_name); 346 return TEE_SUCCESS; 347 } 348 349 FMSG("Probing %s on node %s", drv_name, node_name); 350 351 res = elt->dt_drv->probe(fdt, elt->nodeoffset, elt->dm->compat_data); 352 switch (res) { 353 case TEE_SUCCESS: 354 TAILQ_INSERT_HEAD(&dt_driver_ready_list, elt, link); 355 356 DMSG("element: %s on node %s initialized", drv_name, node_name); 357 break; 358 case TEE_ERROR_DEFER_DRIVER_INIT: 359 elt->deferrals++; 360 TAILQ_INSERT_TAIL(&dt_driver_probe_list, elt, link); 361 362 DMSG("element: %s on node %s deferred %u time(s)", drv_name, 363 node_name, elt->deferrals); 364 break; 365 case TEE_ERROR_NODE_DISABLED: 366 DMSG("element: %s on node %s is disabled", drv_name, node_name); 367 break; 368 default: 369 TAILQ_INSERT_HEAD(&dt_driver_failed_list, elt, link); 370 371 EMSG("Failed to probe %s on node %s: %#"PRIx32, 372 drv_name, node_name, res); 373 break; 374 } 375 376 return res; 377 } 378 379 static TEE_Result alloc_elt_and_probe(const void *fdt, int node, 380 const struct dt_driver *dt_drv, 381 const struct dt_device_match *dm) 382 { 383 struct dt_driver_probe *elt = NULL; 384 385 /* Will be freed when lists are released */ 386 elt = calloc(1, sizeof(*elt)); 387 if (!elt) 388 return TEE_ERROR_OUT_OF_MEMORY; 389 390 elt->nodeoffset = node; 391 elt->dt_drv = dt_drv; 392 elt->dm = dm; 393 elt->type = dt_drv->type; 394 395 return probe_driver_node(fdt, elt); 396 } 397 398 /* Lookup a compatible driver, possibly of a specific @type, for the FDT node */ 399 static TEE_Result probe_device_by_compat(const void *fdt, int node, 400 const char *compat, 401 enum dt_driver_type type) 402 { 403 const struct dt_driver *drv = NULL; 404 const struct dt_device_match *dm = NULL; 405 406 for_each_dt_driver(drv) { 407 if (drv->type != type) 408 continue; 409 410 for (dm = drv->match_table; dm && dm->compatible; dm++) 411 if (strcmp(dm->compatible, compat) == 0) 412 return alloc_elt_and_probe(fdt, node, drv, dm); 413 } 414 415 return TEE_ERROR_ITEM_NOT_FOUND; 416 } 417 418 /* 419 * Lookup the best matching compatible driver, possibly of a specific @type, 420 * for the FDT node. 421 */ 422 TEE_Result dt_driver_probe_device_by_node(const void *fdt, int nodeoffset, 423 enum dt_driver_type type) 424 { 425 int idx = 0; 426 int len = 0; 427 int count = 0; 428 const char *compat = NULL; 429 TEE_Result res = TEE_ERROR_GENERIC; 430 431 assert_type_is_valid(type); 432 433 count = fdt_stringlist_count(fdt, nodeoffset, "compatible"); 434 if (count < 0) 435 return TEE_ERROR_ITEM_NOT_FOUND; 436 437 for (idx = 0; idx < count; idx++) { 438 compat = fdt_stringlist_get(fdt, nodeoffset, "compatible", 439 idx, &len); 440 if (!compat) 441 return TEE_ERROR_GENERIC; 442 443 res = probe_device_by_compat(fdt, nodeoffset, compat, type); 444 445 if (res != TEE_ERROR_ITEM_NOT_FOUND) 446 return res; 447 } 448 449 return TEE_ERROR_ITEM_NOT_FOUND; 450 } 451 452 static TEE_Result process_probe_list(const void *fdt) 453 { 454 struct dt_driver_probe *elt = NULL; 455 struct dt_driver_probe *prev = NULL; 456 static unsigned int __maybe_unused loop_count; 457 static unsigned int __maybe_unused deferral_loop_count; 458 bool __maybe_unused one_deferred = false; 459 bool one_probed_ok = false; 460 461 do { 462 loop_count++; 463 FMSG("Probe loop %u after %u for deferral(s)", loop_count, 464 deferral_loop_count); 465 466 /* Hack here for TRACE_DEBUG messages on probe list elements */ 467 if (TRACE_LEVEL >= TRACE_FLOW) 468 print_probe_list(fdt); 469 470 if (TAILQ_EMPTY(&dt_driver_probe_list)) 471 return TEE_SUCCESS; 472 473 /* 474 * Probe from current end to top. Deferred probed node are 475 * pushed back after current tail for the next probe round. 476 * Reset probe result flags and see status after probe round. 477 */ 478 one_deferred = false; 479 one_probed_ok = false; 480 added_node = false; 481 482 TAILQ_FOREACH_REVERSE_SAFE(elt, &dt_driver_probe_list, 483 dt_driver_probe_head, link, prev) { 484 TAILQ_REMOVE(&dt_driver_probe_list, elt, link); 485 486 switch (probe_driver_node(fdt, elt)) { 487 case TEE_SUCCESS: 488 one_probed_ok = true; 489 break; 490 case TEE_ERROR_DEFER_DRIVER_INIT: 491 one_deferred = true; 492 break; 493 default: 494 break; 495 } 496 } 497 498 if (one_deferred) 499 deferral_loop_count++; 500 501 } while (added_node || one_probed_ok); 502 503 DMSG("Unresolved dependencies after %u rounds, %u deferred", 504 loop_count, deferral_loop_count); 505 506 if (one_deferred) 507 return TEE_ERROR_DEFER_DRIVER_INIT; 508 else 509 return TEE_ERROR_GENERIC; 510 } 511 512 static int driver_probe_compare(struct dt_driver_probe *candidate, 513 struct dt_driver_probe *elt) 514 { 515 if (candidate->nodeoffset != elt->nodeoffset || 516 candidate->type != elt->type) 517 return 1; 518 519 assert(elt->dt_drv == candidate->dt_drv); 520 return 0; 521 } 522 523 /* 524 * Return TEE_SUCCESS if compatible found 525 * TEE_ERROR_OUT_OF_MEMORY if heap is exhausted 526 */ 527 static TEE_Result add_node_to_probe(const void *fdt, int node, 528 const struct dt_driver *dt_drv, 529 const struct dt_device_match *dm) 530 { 531 const char __maybe_unused *node_name = fdt_get_name(fdt, node, NULL); 532 const char __maybe_unused *drv_name = dt_drv->name; 533 struct dt_driver_probe *elt = NULL; 534 struct dt_driver_probe elt_new = { 535 .dm = dm, 536 .dt_drv = dt_drv, 537 .nodeoffset = node, 538 .type = dt_drv->type, 539 }; 540 541 /* If node/type found in probe list or ready list, nothing to do */ 542 TAILQ_FOREACH(elt, &dt_driver_probe_list, link) 543 if (!driver_probe_compare(&elt_new, elt)) 544 return TEE_SUCCESS; 545 546 TAILQ_FOREACH(elt, &dt_driver_ready_list, link) 547 if (!driver_probe_compare(&elt_new, elt)) 548 return TEE_SUCCESS; 549 550 elt = malloc(sizeof(*elt)); 551 if (!elt) 552 return TEE_ERROR_OUT_OF_MEMORY; 553 554 DMSG("element: %s on node %s", node_name, drv_name); 555 556 memcpy(elt, &elt_new, sizeof(*elt)); 557 558 added_node = true; 559 560 TAILQ_INSERT_TAIL(&dt_driver_probe_list, elt, link); 561 562 /* Hack here for TRACE_DEBUG messages on current probe list elements */ 563 if (TRACE_LEVEL >= TRACE_FLOW) 564 print_probe_list(fdt); 565 566 return TEE_SUCCESS; 567 } 568 569 /* 570 * Add a node to the probe list if a dt_driver matches target compatible. 571 * 572 * If @type is DT_DRIVER_ANY, probe list can hold only 1 driver to probe for 573 * the node. A node may probe several drivers if have a unique driver type. 574 * 575 * Return TEE_SUCCESS if compatible found 576 * TEE_ERROR_ITEM_NOT_FOUND if no matching driver 577 * TEE_ERROR_OUT_OF_MEMORY if heap is exhausted 578 */ 579 static TEE_Result add_probe_node_by_compat(const void *fdt, int node, 580 const char *compat) 581 { 582 TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; 583 const struct dt_driver *dt_drv = NULL; 584 const struct dt_device_match *dm = NULL; 585 uint32_t found_types = 0; 586 587 for_each_dt_driver(dt_drv) { 588 for (dm = dt_drv->match_table; dm && dm->compatible; dm++) { 589 if (strcmp(dm->compatible, compat) == 0) { 590 assert(dt_drv->type < 32); 591 592 res = add_node_to_probe(fdt, node, dt_drv, dm); 593 if (res) 594 return res; 595 596 if (found_types & BIT(dt_drv->type)) { 597 EMSG("Driver %s multi hit on type %u", 598 dt_drv->name, dt_drv->type); 599 panic(); 600 } 601 found_types |= BIT(dt_drv->type); 602 603 /* Matching found for this driver, try next */ 604 break; 605 } 606 } 607 } 608 609 return res; 610 } 611 612 /* 613 * Add the node to the probe list if matching compatible drivers are found. 614 * Follow node's compatible property list ordering to find matching driver. 615 */ 616 TEE_Result dt_driver_maybe_add_probe_node(const void *fdt, int node) 617 { 618 int idx = 0; 619 int len = 0; 620 int count = 0; 621 const char *compat = NULL; 622 TEE_Result res = TEE_ERROR_GENERIC; 623 624 if (_fdt_get_status(fdt, node) == DT_STATUS_DISABLED) 625 return TEE_SUCCESS; 626 627 count = fdt_stringlist_count(fdt, node, "compatible"); 628 if (count < 0) 629 return TEE_SUCCESS; 630 631 for (idx = 0; idx < count; idx++) { 632 compat = fdt_stringlist_get(fdt, node, "compatible", idx, &len); 633 assert(compat && len > 0); 634 635 res = add_probe_node_by_compat(fdt, node, compat); 636 637 /* Stop lookup if something was found */ 638 if (res != TEE_ERROR_ITEM_NOT_FOUND) 639 return res; 640 } 641 642 return TEE_SUCCESS; 643 } 644 645 static void parse_node(const void *fdt, int node) 646 { 647 TEE_Result __maybe_unused res = TEE_ERROR_GENERIC; 648 int subnode = 0; 649 650 fdt_for_each_subnode(subnode, fdt, node) { 651 res = dt_driver_maybe_add_probe_node(fdt, subnode); 652 if (res) { 653 EMSG("Failed on node %s with %#"PRIx32, 654 fdt_get_name(fdt, subnode, NULL), res); 655 panic(); 656 } 657 658 /* 659 * Rescursively parse the FDT, skipping disabled nodes. 660 * FDT is expected reliable and core shall have sufficient 661 * stack depth to possibly parse all DT nodes. 662 */ 663 if (IS_ENABLED(CFG_DRIVERS_DT_RECURSIVE_PROBE)) { 664 if (_fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED) 665 continue; 666 667 parse_node(fdt, subnode); 668 } 669 } 670 } 671 672 /* 673 * Parse FDT for nodes and save in probe list the node for which a dt_driver 674 * matches node's compatible property. 675 */ 676 static TEE_Result probe_dt_drivers_early(void) 677 { 678 TEE_Result res = TEE_ERROR_GENERIC; 679 const void *fdt = NULL; 680 681 fdt = get_secure_dt(); 682 if (!fdt) 683 return TEE_SUCCESS; 684 685 parse_node(fdt, fdt_path_offset(fdt, "/")); 686 687 res = process_probe_list(fdt); 688 if (res == TEE_ERROR_DEFER_DRIVER_INIT) { 689 DMSG("Deferred drivers probing"); 690 print_probe_list(fdt); 691 res = TEE_SUCCESS; 692 } 693 694 return res; 695 } 696 697 static TEE_Result probe_dt_drivers(void) 698 { 699 TEE_Result res = TEE_ERROR_GENERIC; 700 const void *fdt = NULL; 701 702 fdt = get_secure_dt(); 703 if (!fdt) 704 return TEE_SUCCESS; 705 706 res = process_probe_list(fdt); 707 if (res || !TAILQ_EMPTY(&dt_driver_failed_list)) { 708 EMSG("Probe sequence result: %#"PRIx32, res); 709 print_probe_list(fdt); 710 } 711 if (res) 712 panic(); 713 714 return TEE_SUCCESS; 715 } 716 717 early_init_late(probe_dt_drivers_early); 718 driver_init(probe_dt_drivers); 719 720 static TEE_Result release_probe_lists(void) 721 { 722 struct dt_driver_probe *elt = NULL; 723 struct dt_driver_probe *next = NULL; 724 struct dt_driver_provider *prov = NULL; 725 struct dt_driver_provider *next_prov = NULL; 726 const void *fdt = NULL; 727 728 fdt = get_secure_dt(); 729 if (!fdt) 730 return TEE_SUCCESS; 731 732 assert(fdt && TAILQ_EMPTY(&dt_driver_probe_list)); 733 734 TAILQ_FOREACH_SAFE(elt, &dt_driver_ready_list, link, next) 735 free(elt); 736 737 TAILQ_FOREACH_SAFE(elt, &dt_driver_failed_list, link, next) 738 free(elt); 739 740 SLIST_FOREACH_SAFE(prov, &dt_driver_provider_list, link, next_prov) 741 free(prov); 742 743 return TEE_SUCCESS; 744 } 745 746 release_init_resource(release_probe_lists); 747 748 /* 749 * Simple bus support: handy to parse subnodes 750 */ 751 static TEE_Result simple_bus_probe(const void *fdt, int node, 752 const void *compat_data __unused) 753 { 754 TEE_Result res = TEE_ERROR_GENERIC; 755 int subnode = 0; 756 757 fdt_for_each_subnode(subnode, fdt, node) { 758 res = dt_driver_maybe_add_probe_node(fdt, subnode); 759 if (res) { 760 EMSG("Failed on node %s with %#"PRIx32, 761 fdt_get_name(fdt, subnode, NULL), res); 762 panic(); 763 } 764 } 765 766 return TEE_SUCCESS; 767 } 768 769 static const struct dt_device_match simple_bus_match_table[] = { 770 { .compatible = "simple-bus" }, 771 { } 772 }; 773 774 DEFINE_DT_DRIVER(simple_bus_dt_driver) = { 775 .name = "simple-bus", 776 .match_table = simple_bus_match_table, 777 .probe = simple_bus_probe, 778 }; 779