1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2012, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/acpi.h> 7 #include <linux/types.h> 8 #include <linux/err.h> 9 #include <linux/slab.h> 10 #include <linux/clk.h> 11 #include <linux/of.h> 12 #include <linux/of_graph.h> 13 #include <linux/platform_device.h> 14 #include <linux/amba/bus.h> 15 #include <linux/coresight.h> 16 #include <linux/cpumask.h> 17 #include <asm/smp_plat.h> 18 19 #include "coresight-priv.h" 20 21 /* 22 * Add an entry to the connection list and assign @conn's contents to it. 23 * 24 * If the output port is already assigned on this device, return -EINVAL 25 */ 26 struct coresight_connection * 27 coresight_add_out_conn(struct device *dev, 28 struct coresight_platform_data *pdata, 29 const struct coresight_connection *new_conn) 30 { 31 int i; 32 struct coresight_connection *conn; 33 34 /* 35 * Warn on any existing duplicate output port. 36 */ 37 for (i = 0; i < pdata->nr_outconns; ++i) { 38 conn = pdata->out_conns[i]; 39 /* Output == -1 means ignore the port for example for helpers */ 40 if (conn->src_port != -1 && 41 conn->src_port == new_conn->src_port) { 42 dev_warn(dev, "Duplicate output port %d\n", 43 conn->src_port); 44 return ERR_PTR(-EINVAL); 45 } 46 } 47 48 pdata->nr_outconns++; 49 pdata->out_conns = 50 devm_krealloc_array(dev, pdata->out_conns, pdata->nr_outconns, 51 sizeof(*pdata->out_conns), GFP_KERNEL); 52 if (!pdata->out_conns) 53 return ERR_PTR(-ENOMEM); 54 55 conn = devm_kmalloc(dev, sizeof(struct coresight_connection), 56 GFP_KERNEL); 57 if (!conn) 58 return ERR_PTR(-ENOMEM); 59 60 /* 61 * Copy the new connection into the allocation, save the pointer to the 62 * end of the connection array and also return it in case it needs to be 63 * used right away. 64 */ 65 *conn = *new_conn; 66 pdata->out_conns[pdata->nr_outconns - 1] = conn; 67 return conn; 68 } 69 EXPORT_SYMBOL_GPL(coresight_add_out_conn); 70 71 /* 72 * Add an input connection reference to @out_conn in the target's in_conns array 73 * 74 * @out_conn: Existing output connection to store as an input on the 75 * connection's remote device. 76 */ 77 int coresight_add_in_conn(struct coresight_connection *out_conn) 78 { 79 int i; 80 struct device *dev = out_conn->dest_dev->dev.parent; 81 struct coresight_platform_data *pdata = out_conn->dest_dev->pdata; 82 83 for (i = 0; i < pdata->nr_inconns; ++i) 84 if (!pdata->in_conns[i]) { 85 pdata->in_conns[i] = out_conn; 86 return 0; 87 } 88 89 pdata->nr_inconns++; 90 pdata->in_conns = 91 devm_krealloc_array(dev, pdata->in_conns, pdata->nr_inconns, 92 sizeof(*pdata->in_conns), GFP_KERNEL); 93 if (!pdata->in_conns) 94 return -ENOMEM; 95 pdata->in_conns[pdata->nr_inconns - 1] = out_conn; 96 return 0; 97 } 98 EXPORT_SYMBOL_GPL(coresight_add_in_conn); 99 100 static struct device * 101 coresight_find_device_by_fwnode(struct fwnode_handle *fwnode) 102 { 103 struct device *dev = NULL; 104 105 /* 106 * If we have a non-configurable replicator, it will be found on the 107 * platform bus. 108 */ 109 dev = bus_find_device_by_fwnode(&platform_bus_type, fwnode); 110 if (dev) 111 return dev; 112 113 /* 114 * We have a configurable component - circle through the AMBA bus 115 * looking for the device that matches the endpoint node. 116 */ 117 return bus_find_device_by_fwnode(&amba_bustype, fwnode); 118 } 119 120 /* 121 * Find a registered coresight device from a device fwnode. 122 * The node info is associated with the AMBA parent, but the 123 * csdev keeps a copy so iterate round the coresight bus to 124 * find the device. 125 */ 126 struct coresight_device * 127 coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode) 128 { 129 struct device *dev; 130 struct coresight_device *csdev = NULL; 131 132 dev = bus_find_device_by_fwnode(&coresight_bustype, r_fwnode); 133 if (dev) { 134 csdev = to_coresight_device(dev); 135 put_device(dev); 136 } 137 return csdev; 138 } 139 EXPORT_SYMBOL_GPL(coresight_find_csdev_by_fwnode); 140 141 #ifdef CONFIG_OF 142 static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep) 143 { 144 return of_property_read_bool(ep, "slave-mode"); 145 } 146 147 static struct device_node *of_coresight_get_port_parent(struct device_node *ep) 148 { 149 struct device_node *parent = of_graph_get_port_parent(ep); 150 151 /* 152 * Skip one-level up to the real device node, if we 153 * are using the new bindings. 154 */ 155 if (of_node_name_eq(parent, "in-ports") || 156 of_node_name_eq(parent, "out-ports")) 157 parent = of_get_next_parent(parent); 158 159 return parent; 160 } 161 162 static inline struct device_node * 163 of_coresight_get_output_ports_node(const struct device_node *node) 164 { 165 return of_get_child_by_name(node, "out-ports"); 166 } 167 168 static int of_coresight_get_cpu(struct device *dev) 169 { 170 int cpu; 171 struct device_node *dn; 172 173 if (!dev->of_node) 174 return -ENODEV; 175 176 dn = of_parse_phandle(dev->of_node, "cpu", 0); 177 if (!dn) 178 return -ENODEV; 179 180 cpu = of_cpu_node_to_id(dn); 181 of_node_put(dn); 182 183 return cpu; 184 } 185 186 /* 187 * of_coresight_parse_endpoint : Parse the given output endpoint @ep 188 * and fill the connection information in @pdata->out_conns 189 * 190 * Parses the local port, remote device name and the remote port. 191 * 192 * Returns : 193 * 0 - If the parsing completed without any fatal errors. 194 * -Errno - Fatal error, abort the scanning. 195 */ 196 static int of_coresight_parse_endpoint(struct device *dev, 197 struct device_node *ep, 198 struct coresight_platform_data *pdata) 199 { 200 int ret = 0; 201 struct of_endpoint endpoint, rendpoint; 202 struct device_node *rparent = NULL; 203 struct device_node *rep = NULL; 204 struct device *rdev = NULL; 205 struct fwnode_handle *rdev_fwnode; 206 struct coresight_connection conn = {}; 207 struct coresight_connection *new_conn; 208 209 do { 210 /* Parse the local port details */ 211 if (of_graph_parse_endpoint(ep, &endpoint)) 212 break; 213 /* 214 * Get a handle on the remote endpoint and the device it is 215 * attached to. 216 */ 217 rep = of_graph_get_remote_endpoint(ep); 218 if (!rep) 219 break; 220 rparent = of_coresight_get_port_parent(rep); 221 if (!rparent) 222 break; 223 if (of_graph_parse_endpoint(rep, &rendpoint)) 224 break; 225 226 rdev_fwnode = of_fwnode_handle(rparent); 227 /* If the remote device is not available, defer probing */ 228 rdev = coresight_find_device_by_fwnode(rdev_fwnode); 229 if (!rdev) { 230 ret = -EPROBE_DEFER; 231 break; 232 } 233 234 conn.src_port = endpoint.port; 235 /* 236 * Hold the refcount to the target device. This could be 237 * released via: 238 * 1) coresight_release_platform_data() if the probe fails or 239 * this device is unregistered. 240 * 2) While removing the target device via 241 * coresight_remove_match() 242 */ 243 conn.dest_fwnode = fwnode_handle_get(rdev_fwnode); 244 conn.dest_port = rendpoint.port; 245 246 new_conn = coresight_add_out_conn(dev, pdata, &conn); 247 if (IS_ERR_VALUE(new_conn)) { 248 fwnode_handle_put(conn.dest_fwnode); 249 return PTR_ERR(new_conn); 250 } 251 /* Connection record updated */ 252 } while (0); 253 254 of_node_put(rparent); 255 of_node_put(rep); 256 put_device(rdev); 257 258 return ret; 259 } 260 261 static int of_get_coresight_platform_data(struct device *dev, 262 struct coresight_platform_data *pdata) 263 { 264 int ret = 0; 265 struct device_node *ep = NULL; 266 const struct device_node *parent = NULL; 267 bool legacy_binding = false; 268 struct device_node *node = dev->of_node; 269 270 parent = of_coresight_get_output_ports_node(node); 271 /* 272 * If the DT uses obsoleted bindings, the ports are listed 273 * under the device and we need to filter out the input 274 * ports. 275 */ 276 if (!parent) { 277 /* 278 * Avoid warnings in of_graph_get_next_endpoint() 279 * if the device doesn't have any graph connections 280 */ 281 if (!of_graph_is_present(node)) 282 return 0; 283 legacy_binding = true; 284 parent = node; 285 dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n"); 286 } 287 288 /* Iterate through each output port to discover topology */ 289 while ((ep = of_graph_get_next_endpoint(parent, ep))) { 290 /* 291 * Legacy binding mixes input/output ports under the 292 * same parent. So, skip the input ports if we are dealing 293 * with legacy binding, as they processed with their 294 * connected output ports. 295 */ 296 if (legacy_binding && of_coresight_legacy_ep_is_input(ep)) 297 continue; 298 299 ret = of_coresight_parse_endpoint(dev, ep, pdata); 300 if (ret) 301 return ret; 302 } 303 304 return 0; 305 } 306 #else 307 static inline int 308 of_get_coresight_platform_data(struct device *dev, 309 struct coresight_platform_data *pdata) 310 { 311 return -ENOENT; 312 } 313 314 static inline int of_coresight_get_cpu(struct device *dev) 315 { 316 return -ENODEV; 317 } 318 #endif 319 320 #ifdef CONFIG_ACPI 321 322 #include <acpi/actypes.h> 323 #include <acpi/processor.h> 324 325 /* ACPI Graph _DSD UUID : "ab02a46b-74c7-45a2-bd68-f7d344ef2153" */ 326 static const guid_t acpi_graph_uuid = GUID_INIT(0xab02a46b, 0x74c7, 0x45a2, 327 0xbd, 0x68, 0xf7, 0xd3, 328 0x44, 0xef, 0x21, 0x53); 329 /* Coresight ACPI Graph UUID : "3ecbc8b6-1d0e-4fb3-8107-e627f805c6cd" */ 330 static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3, 331 0x81, 0x07, 0xe6, 0x27, 332 0xf8, 0x05, 0xc6, 0xcd); 333 #define ACPI_CORESIGHT_LINK_SLAVE 0 334 #define ACPI_CORESIGHT_LINK_MASTER 1 335 336 static inline bool is_acpi_guid(const union acpi_object *obj) 337 { 338 return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16); 339 } 340 341 /* 342 * acpi_guid_matches - Checks if the given object is a GUID object and 343 * that it matches the supplied the GUID. 344 */ 345 static inline bool acpi_guid_matches(const union acpi_object *obj, 346 const guid_t *guid) 347 { 348 return is_acpi_guid(obj) && 349 guid_equal((guid_t *)obj->buffer.pointer, guid); 350 } 351 352 static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj) 353 { 354 return acpi_guid_matches(obj, &acpi_graph_uuid); 355 } 356 357 static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj) 358 { 359 return acpi_guid_matches(obj, &coresight_graph_uuid); 360 } 361 362 static inline bool is_acpi_coresight_graph(const union acpi_object *obj) 363 { 364 const union acpi_object *graphid, *guid, *links; 365 366 if (obj->type != ACPI_TYPE_PACKAGE || 367 obj->package.count < 3) 368 return false; 369 370 graphid = &obj->package.elements[0]; 371 guid = &obj->package.elements[1]; 372 links = &obj->package.elements[2]; 373 374 if (graphid->type != ACPI_TYPE_INTEGER || 375 links->type != ACPI_TYPE_INTEGER) 376 return false; 377 378 return is_acpi_coresight_graph_guid(guid); 379 } 380 381 /* 382 * acpi_validate_dsd_graph - Make sure the given _DSD graph conforms 383 * to the ACPI _DSD Graph specification. 384 * 385 * ACPI Devices Graph property has the following format: 386 * { 387 * Revision - Integer, must be 0 388 * NumberOfGraphs - Integer, N indicating the following list. 389 * Graph[1], 390 * ... 391 * Graph[N] 392 * } 393 * 394 * And each Graph entry has the following format: 395 * { 396 * GraphID - Integer, identifying a graph the device belongs to. 397 * UUID - UUID identifying the specification that governs 398 * this graph. (e.g, see is_acpi_coresight_graph()) 399 * NumberOfLinks - Number "N" of connections on this node of the graph. 400 * Links[1] 401 * ... 402 * Links[N] 403 * } 404 * 405 * Where each "Links" entry has the following format: 406 * 407 * { 408 * SourcePortAddress - Integer 409 * DestinationPortAddress - Integer 410 * DestinationDeviceName - Reference to another device 411 * ( --- CoreSight specific extensions below ---) 412 * DirectionOfFlow - Integer 1 for output(master) 413 * 0 for input(slave) 414 * } 415 * 416 * e.g: 417 * For a Funnel device 418 * 419 * Device(MFUN) { 420 * ... 421 * 422 * Name (_DSD, Package() { 423 * // DSD Package contains tuples of { Proeprty_Type_UUID, Package() } 424 * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), //Std. Property UUID 425 * Package() { 426 * Package(2) { "property-name", <property-value> } 427 * }, 428 * 429 * ToUUID("ab02a46b-74c7-45a2-bd68-f7d344ef2153"), // ACPI Graph UUID 430 * Package() { 431 * 0, // Revision 432 * 1, // NumberOfGraphs. 433 * Package() { // Graph[0] Package 434 * 1, // GraphID 435 * // Coresight Graph UUID 436 * ToUUID("3ecbc8b6-1d0e-4fb3-8107-e627f805c6cd"), 437 * 3, // NumberOfLinks aka ports 438 * // Link[0]: Output_0 -> Replicator:Input_0 439 * Package () { 0, 0, \_SB_.RPL0, 1 }, 440 * // Link[1]: Input_0 <- Cluster0_Funnel0:Output_0 441 * Package () { 0, 0, \_SB_.CLU0.FUN0, 0 }, 442 * // Link[2]: Input_1 <- Cluster1_Funnel0:Output_0 443 * Package () { 1, 0, \_SB_.CLU1.FUN0, 0 }, 444 * } // End of Graph[0] Package 445 * 446 * }, // End of ACPI Graph Property 447 * }) 448 */ 449 static inline bool acpi_validate_dsd_graph(const union acpi_object *graph) 450 { 451 int i, n; 452 const union acpi_object *rev, *nr_graphs; 453 454 /* The graph must contain at least the Revision and Number of Graphs */ 455 if (graph->package.count < 2) 456 return false; 457 458 rev = &graph->package.elements[0]; 459 nr_graphs = &graph->package.elements[1]; 460 461 if (rev->type != ACPI_TYPE_INTEGER || 462 nr_graphs->type != ACPI_TYPE_INTEGER) 463 return false; 464 465 /* We only support revision 0 */ 466 if (rev->integer.value != 0) 467 return false; 468 469 n = nr_graphs->integer.value; 470 /* CoreSight devices are only part of a single Graph */ 471 if (n != 1) 472 return false; 473 474 /* Make sure the ACPI graph package has right number of elements */ 475 if (graph->package.count != (n + 2)) 476 return false; 477 478 /* 479 * Each entry must be a graph package with at least 3 members : 480 * { GraphID, UUID, NumberOfLinks(n), Links[.],... } 481 */ 482 for (i = 2; i < n + 2; i++) { 483 const union acpi_object *obj = &graph->package.elements[i]; 484 485 if (obj->type != ACPI_TYPE_PACKAGE || 486 obj->package.count < 3) 487 return false; 488 } 489 490 return true; 491 } 492 493 /* acpi_get_dsd_graph - Find the _DSD Graph property for the given device. */ 494 static const union acpi_object * 495 acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf) 496 { 497 int i; 498 acpi_status status; 499 const union acpi_object *dsd; 500 501 status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, 502 buf, ACPI_TYPE_PACKAGE); 503 if (ACPI_FAILURE(status)) 504 return NULL; 505 506 dsd = buf->pointer; 507 508 /* 509 * _DSD property consists tuples { Prop_UUID, Package() } 510 * Iterate through all the packages and find the Graph. 511 */ 512 for (i = 0; i + 1 < dsd->package.count; i += 2) { 513 const union acpi_object *guid, *package; 514 515 guid = &dsd->package.elements[i]; 516 package = &dsd->package.elements[i + 1]; 517 518 /* All _DSD elements must have a UUID and a Package */ 519 if (!is_acpi_guid(guid) || package->type != ACPI_TYPE_PACKAGE) 520 break; 521 /* Skip the non-Graph _DSD packages */ 522 if (!is_acpi_dsd_graph_guid(guid)) 523 continue; 524 if (acpi_validate_dsd_graph(package)) 525 return package; 526 /* Invalid graph format, continue */ 527 dev_warn(&adev->dev, "Invalid Graph _DSD property\n"); 528 } 529 530 return NULL; 531 } 532 533 static inline bool 534 acpi_validate_coresight_graph(const union acpi_object *cs_graph) 535 { 536 int nlinks; 537 538 nlinks = cs_graph->package.elements[2].integer.value; 539 /* 540 * Graph must have the following fields : 541 * { GraphID, GraphUUID, NumberOfLinks, Links... } 542 */ 543 if (cs_graph->package.count != (nlinks + 3)) 544 return false; 545 /* The links are validated in acpi_coresight_parse_link() */ 546 return true; 547 } 548 549 /* 550 * acpi_get_coresight_graph - Parse the device _DSD tables and find 551 * the Graph property matching the CoreSight Graphs. 552 * 553 * Returns the pointer to the CoreSight Graph Package when found. Otherwise 554 * returns NULL. 555 */ 556 static const union acpi_object * 557 acpi_get_coresight_graph(struct acpi_device *adev, struct acpi_buffer *buf) 558 { 559 const union acpi_object *graph_list, *graph; 560 int i, nr_graphs; 561 562 graph_list = acpi_get_dsd_graph(adev, buf); 563 if (!graph_list) 564 return graph_list; 565 566 nr_graphs = graph_list->package.elements[1].integer.value; 567 568 for (i = 2; i < nr_graphs + 2; i++) { 569 graph = &graph_list->package.elements[i]; 570 if (!is_acpi_coresight_graph(graph)) 571 continue; 572 if (acpi_validate_coresight_graph(graph)) 573 return graph; 574 /* Invalid graph format */ 575 break; 576 } 577 578 return NULL; 579 } 580 581 /* 582 * acpi_coresight_parse_link - Parse the given Graph connection 583 * of the device and populate the coresight_connection for an output 584 * connection. 585 * 586 * CoreSight Graph specification mandates that the direction of the data 587 * flow must be specified in the link. i.e, 588 * 589 * SourcePortAddress, // Integer 590 * DestinationPortAddress, // Integer 591 * DestinationDeviceName, // Reference to another device 592 * DirectionOfFlow, // 1 for output(master), 0 for input(slave) 593 * 594 * Returns the direction of the data flow [ Input(slave) or Output(master) ] 595 * upon success. 596 * Returns an negative error number otherwise. 597 */ 598 static int acpi_coresight_parse_link(struct acpi_device *adev, 599 const union acpi_object *link, 600 struct coresight_connection *conn) 601 { 602 int dir; 603 const union acpi_object *fields; 604 struct acpi_device *r_adev; 605 struct device *rdev; 606 607 if (link->type != ACPI_TYPE_PACKAGE || 608 link->package.count != 4) 609 return -EINVAL; 610 611 fields = link->package.elements; 612 613 if (fields[0].type != ACPI_TYPE_INTEGER || 614 fields[1].type != ACPI_TYPE_INTEGER || 615 fields[2].type != ACPI_TYPE_LOCAL_REFERENCE || 616 fields[3].type != ACPI_TYPE_INTEGER) 617 return -EINVAL; 618 619 r_adev = acpi_fetch_acpi_dev(fields[2].reference.handle); 620 if (!r_adev) 621 return -ENODEV; 622 623 dir = fields[3].integer.value; 624 if (dir == ACPI_CORESIGHT_LINK_MASTER) { 625 conn->src_port = fields[0].integer.value; 626 conn->dest_port = fields[1].integer.value; 627 rdev = coresight_find_device_by_fwnode(&r_adev->fwnode); 628 if (!rdev) 629 return -EPROBE_DEFER; 630 /* 631 * Hold the refcount to the target device. This could be 632 * released via: 633 * 1) coresight_release_platform_data() if the probe fails or 634 * this device is unregistered. 635 * 2) While removing the target device via 636 * coresight_remove_match(). 637 */ 638 conn->dest_fwnode = fwnode_handle_get(&r_adev->fwnode); 639 } else if (dir == ACPI_CORESIGHT_LINK_SLAVE) { 640 /* 641 * We are only interested in the port number 642 * for the input ports at this component. 643 * Store the port number in child_port. 644 */ 645 conn->dest_port = fields[0].integer.value; 646 } else { 647 /* Invalid direction */ 648 return -EINVAL; 649 } 650 651 return dir; 652 } 653 654 /* 655 * acpi_coresight_parse_graph - Parse the _DSD CoreSight graph 656 * connection information and populate the supplied coresight_platform_data 657 * instance. 658 */ 659 static int acpi_coresight_parse_graph(struct device *dev, 660 struct acpi_device *adev, 661 struct coresight_platform_data *pdata) 662 { 663 int ret = 0; 664 int i, nlinks; 665 const union acpi_object *graph; 666 struct coresight_connection conn, zero_conn = {}; 667 struct coresight_connection *new_conn; 668 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 669 670 graph = acpi_get_coresight_graph(adev, &buf); 671 /* 672 * There are no graph connections, which is fine for some components. 673 * e.g., ETE 674 */ 675 if (!graph) 676 goto free; 677 678 nlinks = graph->package.elements[2].integer.value; 679 if (!nlinks) 680 goto free; 681 682 for (i = 0; i < nlinks; i++) { 683 const union acpi_object *link = &graph->package.elements[3 + i]; 684 int dir; 685 686 conn = zero_conn; 687 dir = acpi_coresight_parse_link(adev, link, &conn); 688 if (dir < 0) { 689 ret = dir; 690 goto free; 691 } 692 693 if (dir == ACPI_CORESIGHT_LINK_MASTER) { 694 new_conn = coresight_add_out_conn(dev, pdata, &conn); 695 if (IS_ERR(new_conn)) { 696 ret = PTR_ERR(new_conn); 697 goto free; 698 } 699 } 700 } 701 702 free: 703 /* 704 * When ACPI fails to alloc a buffer, it will free the buffer 705 * created via ACPI_ALLOCATE_BUFFER and set to NULL. 706 * ACPI_FREE can handle NULL pointers, so free it directly. 707 */ 708 ACPI_FREE(buf.pointer); 709 return ret; 710 } 711 712 /* 713 * acpi_handle_to_logical_cpuid - Map a given acpi_handle to the 714 * logical CPU id of the corresponding CPU device. 715 * 716 * Returns the logical CPU id when found. Otherwise returns >= nr_cpus_id. 717 */ 718 static int 719 acpi_handle_to_logical_cpuid(acpi_handle handle) 720 { 721 int i; 722 struct acpi_processor *pr; 723 724 for_each_possible_cpu(i) { 725 pr = per_cpu(processors, i); 726 if (pr && pr->handle == handle) 727 break; 728 } 729 730 return i; 731 } 732 733 /* 734 * acpi_coresigh_get_cpu - Find the logical CPU id of the CPU associated 735 * with this coresight device. With ACPI bindings, the CoreSight components 736 * are listed as child device of the associated CPU. 737 * 738 * Returns the logical CPU id when found. Otherwise returns 0. 739 */ 740 static int acpi_coresight_get_cpu(struct device *dev) 741 { 742 int cpu; 743 acpi_handle cpu_handle; 744 acpi_status status; 745 struct acpi_device *adev = ACPI_COMPANION(dev); 746 747 if (!adev) 748 return -ENODEV; 749 status = acpi_get_parent(adev->handle, &cpu_handle); 750 if (ACPI_FAILURE(status)) 751 return -ENODEV; 752 753 cpu = acpi_handle_to_logical_cpuid(cpu_handle); 754 if (cpu >= nr_cpu_ids) 755 return -ENODEV; 756 return cpu; 757 } 758 759 static int 760 acpi_get_coresight_platform_data(struct device *dev, 761 struct coresight_platform_data *pdata) 762 { 763 struct acpi_device *adev; 764 765 adev = ACPI_COMPANION(dev); 766 if (!adev) 767 return -EINVAL; 768 769 return acpi_coresight_parse_graph(dev, adev, pdata); 770 } 771 772 #else 773 774 static inline int 775 acpi_get_coresight_platform_data(struct device *dev, 776 struct coresight_platform_data *pdata) 777 { 778 return -ENOENT; 779 } 780 781 static inline int acpi_coresight_get_cpu(struct device *dev) 782 { 783 return -ENODEV; 784 } 785 #endif 786 787 int coresight_get_cpu(struct device *dev) 788 { 789 if (is_of_node(dev->fwnode)) 790 return of_coresight_get_cpu(dev); 791 else if (is_acpi_device_node(dev->fwnode)) 792 return acpi_coresight_get_cpu(dev); 793 return 0; 794 } 795 EXPORT_SYMBOL_GPL(coresight_get_cpu); 796 797 struct coresight_platform_data * 798 coresight_get_platform_data(struct device *dev) 799 { 800 int ret = -ENOENT; 801 struct coresight_platform_data *pdata = NULL; 802 struct fwnode_handle *fwnode = dev_fwnode(dev); 803 804 if (IS_ERR_OR_NULL(fwnode)) 805 goto error; 806 807 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 808 if (!pdata) { 809 ret = -ENOMEM; 810 goto error; 811 } 812 813 if (is_of_node(fwnode)) 814 ret = of_get_coresight_platform_data(dev, pdata); 815 else if (is_acpi_device_node(fwnode)) 816 ret = acpi_get_coresight_platform_data(dev, pdata); 817 818 if (!ret) 819 return pdata; 820 error: 821 if (!IS_ERR_OR_NULL(pdata)) 822 /* Cleanup the connection information */ 823 coresight_release_platform_data(NULL, dev, pdata); 824 return ERR_PTR(ret); 825 } 826 EXPORT_SYMBOL_GPL(coresight_get_platform_data); 827