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