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