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