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 for_each_endpoint_of_node() 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 for_each_endpoint_of_node(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 of_node_put(ep); 302 return ret; 303 } 304 } 305 306 return 0; 307 } 308 #else 309 static inline int 310 of_get_coresight_platform_data(struct device *dev, 311 struct coresight_platform_data *pdata) 312 { 313 return -ENOENT; 314 } 315 316 static inline int of_coresight_get_cpu(struct device *dev) 317 { 318 return -ENODEV; 319 } 320 #endif 321 322 #ifdef CONFIG_ACPI 323 324 #include <acpi/actypes.h> 325 #include <acpi/processor.h> 326 327 /* ACPI Graph _DSD UUID : "ab02a46b-74c7-45a2-bd68-f7d344ef2153" */ 328 static const guid_t acpi_graph_uuid = GUID_INIT(0xab02a46b, 0x74c7, 0x45a2, 329 0xbd, 0x68, 0xf7, 0xd3, 330 0x44, 0xef, 0x21, 0x53); 331 /* Coresight ACPI Graph UUID : "3ecbc8b6-1d0e-4fb3-8107-e627f805c6cd" */ 332 static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3, 333 0x81, 0x07, 0xe6, 0x27, 334 0xf8, 0x05, 0xc6, 0xcd); 335 #define ACPI_CORESIGHT_LINK_SLAVE 0 336 #define ACPI_CORESIGHT_LINK_MASTER 1 337 338 static inline bool is_acpi_guid(const union acpi_object *obj) 339 { 340 return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16); 341 } 342 343 /* 344 * acpi_guid_matches - Checks if the given object is a GUID object and 345 * that it matches the supplied the GUID. 346 */ 347 static inline bool acpi_guid_matches(const union acpi_object *obj, 348 const guid_t *guid) 349 { 350 return is_acpi_guid(obj) && 351 guid_equal((guid_t *)obj->buffer.pointer, guid); 352 } 353 354 static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj) 355 { 356 return acpi_guid_matches(obj, &acpi_graph_uuid); 357 } 358 359 static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj) 360 { 361 return acpi_guid_matches(obj, &coresight_graph_uuid); 362 } 363 364 static inline bool is_acpi_coresight_graph(const union acpi_object *obj) 365 { 366 const union acpi_object *graphid, *guid, *links; 367 368 if (obj->type != ACPI_TYPE_PACKAGE || 369 obj->package.count < 3) 370 return false; 371 372 graphid = &obj->package.elements[0]; 373 guid = &obj->package.elements[1]; 374 links = &obj->package.elements[2]; 375 376 if (graphid->type != ACPI_TYPE_INTEGER || 377 links->type != ACPI_TYPE_INTEGER) 378 return false; 379 380 return is_acpi_coresight_graph_guid(guid); 381 } 382 383 /* 384 * acpi_validate_dsd_graph - Make sure the given _DSD graph conforms 385 * to the ACPI _DSD Graph specification. 386 * 387 * ACPI Devices Graph property has the following format: 388 * { 389 * Revision - Integer, must be 0 390 * NumberOfGraphs - Integer, N indicating the following list. 391 * Graph[1], 392 * ... 393 * Graph[N] 394 * } 395 * 396 * And each Graph entry has the following format: 397 * { 398 * GraphID - Integer, identifying a graph the device belongs to. 399 * UUID - UUID identifying the specification that governs 400 * this graph. (e.g, see is_acpi_coresight_graph()) 401 * NumberOfLinks - Number "N" of connections on this node of the graph. 402 * Links[1] 403 * ... 404 * Links[N] 405 * } 406 * 407 * Where each "Links" entry has the following format: 408 * 409 * { 410 * SourcePortAddress - Integer 411 * DestinationPortAddress - Integer 412 * DestinationDeviceName - Reference to another device 413 * ( --- CoreSight specific extensions below ---) 414 * DirectionOfFlow - Integer 1 for output(master) 415 * 0 for input(slave) 416 * } 417 * 418 * e.g: 419 * For a Funnel device 420 * 421 * Device(MFUN) { 422 * ... 423 * 424 * Name (_DSD, Package() { 425 * // DSD Package contains tuples of { Proeprty_Type_UUID, Package() } 426 * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), //Std. Property UUID 427 * Package() { 428 * Package(2) { "property-name", <property-value> } 429 * }, 430 * 431 * ToUUID("ab02a46b-74c7-45a2-bd68-f7d344ef2153"), // ACPI Graph UUID 432 * Package() { 433 * 0, // Revision 434 * 1, // NumberOfGraphs. 435 * Package() { // Graph[0] Package 436 * 1, // GraphID 437 * // Coresight Graph UUID 438 * ToUUID("3ecbc8b6-1d0e-4fb3-8107-e627f805c6cd"), 439 * 3, // NumberOfLinks aka ports 440 * // Link[0]: Output_0 -> Replicator:Input_0 441 * Package () { 0, 0, \_SB_.RPL0, 1 }, 442 * // Link[1]: Input_0 <- Cluster0_Funnel0:Output_0 443 * Package () { 0, 0, \_SB_.CLU0.FUN0, 0 }, 444 * // Link[2]: Input_1 <- Cluster1_Funnel0:Output_0 445 * Package () { 1, 0, \_SB_.CLU1.FUN0, 0 }, 446 * } // End of Graph[0] Package 447 * 448 * }, // End of ACPI Graph Property 449 * }) 450 */ 451 static inline bool acpi_validate_dsd_graph(const union acpi_object *graph) 452 { 453 int i, n; 454 const union acpi_object *rev, *nr_graphs; 455 456 /* The graph must contain at least the Revision and Number of Graphs */ 457 if (graph->package.count < 2) 458 return false; 459 460 rev = &graph->package.elements[0]; 461 nr_graphs = &graph->package.elements[1]; 462 463 if (rev->type != ACPI_TYPE_INTEGER || 464 nr_graphs->type != ACPI_TYPE_INTEGER) 465 return false; 466 467 /* We only support revision 0 */ 468 if (rev->integer.value != 0) 469 return false; 470 471 n = nr_graphs->integer.value; 472 /* CoreSight devices are only part of a single Graph */ 473 if (n != 1) 474 return false; 475 476 /* Make sure the ACPI graph package has right number of elements */ 477 if (graph->package.count != (n + 2)) 478 return false; 479 480 /* 481 * Each entry must be a graph package with at least 3 members : 482 * { GraphID, UUID, NumberOfLinks(n), Links[.],... } 483 */ 484 for (i = 2; i < n + 2; i++) { 485 const union acpi_object *obj = &graph->package.elements[i]; 486 487 if (obj->type != ACPI_TYPE_PACKAGE || 488 obj->package.count < 3) 489 return false; 490 } 491 492 return true; 493 } 494 495 /* acpi_get_dsd_graph - Find the _DSD Graph property for the given device. */ 496 static const union acpi_object * 497 acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf) 498 { 499 int i; 500 acpi_status status; 501 const union acpi_object *dsd; 502 503 status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, 504 buf, ACPI_TYPE_PACKAGE); 505 if (ACPI_FAILURE(status)) 506 return NULL; 507 508 dsd = buf->pointer; 509 510 /* 511 * _DSD property consists tuples { Prop_UUID, Package() } 512 * Iterate through all the packages and find the Graph. 513 */ 514 for (i = 0; i + 1 < dsd->package.count; i += 2) { 515 const union acpi_object *guid, *package; 516 517 guid = &dsd->package.elements[i]; 518 package = &dsd->package.elements[i + 1]; 519 520 /* All _DSD elements must have a UUID and a Package */ 521 if (!is_acpi_guid(guid) || package->type != ACPI_TYPE_PACKAGE) 522 break; 523 /* Skip the non-Graph _DSD packages */ 524 if (!is_acpi_dsd_graph_guid(guid)) 525 continue; 526 if (acpi_validate_dsd_graph(package)) 527 return package; 528 /* Invalid graph format, continue */ 529 dev_warn(&adev->dev, "Invalid Graph _DSD property\n"); 530 } 531 532 return NULL; 533 } 534 535 static inline bool 536 acpi_validate_coresight_graph(const union acpi_object *cs_graph) 537 { 538 int nlinks; 539 540 nlinks = cs_graph->package.elements[2].integer.value; 541 /* 542 * Graph must have the following fields : 543 * { GraphID, GraphUUID, NumberOfLinks, Links... } 544 */ 545 if (cs_graph->package.count != (nlinks + 3)) 546 return false; 547 /* The links are validated in acpi_coresight_parse_link() */ 548 return true; 549 } 550 551 /* 552 * acpi_get_coresight_graph - Parse the device _DSD tables and find 553 * the Graph property matching the CoreSight Graphs. 554 * 555 * Returns the pointer to the CoreSight Graph Package when found. Otherwise 556 * returns NULL. 557 */ 558 static const union acpi_object * 559 acpi_get_coresight_graph(struct acpi_device *adev, struct acpi_buffer *buf) 560 { 561 const union acpi_object *graph_list, *graph; 562 int i, nr_graphs; 563 564 graph_list = acpi_get_dsd_graph(adev, buf); 565 if (!graph_list) 566 return graph_list; 567 568 nr_graphs = graph_list->package.elements[1].integer.value; 569 570 for (i = 2; i < nr_graphs + 2; i++) { 571 graph = &graph_list->package.elements[i]; 572 if (!is_acpi_coresight_graph(graph)) 573 continue; 574 if (acpi_validate_coresight_graph(graph)) 575 return graph; 576 /* Invalid graph format */ 577 break; 578 } 579 580 return NULL; 581 } 582 583 /* 584 * acpi_coresight_parse_link - Parse the given Graph connection 585 * of the device and populate the coresight_connection for an output 586 * connection. 587 * 588 * CoreSight Graph specification mandates that the direction of the data 589 * flow must be specified in the link. i.e, 590 * 591 * SourcePortAddress, // Integer 592 * DestinationPortAddress, // Integer 593 * DestinationDeviceName, // Reference to another device 594 * DirectionOfFlow, // 1 for output(master), 0 for input(slave) 595 * 596 * Returns the direction of the data flow [ Input(slave) or Output(master) ] 597 * upon success. 598 * Returns an negative error number otherwise. 599 */ 600 static int acpi_coresight_parse_link(struct acpi_device *adev, 601 const union acpi_object *link, 602 struct coresight_connection *conn) 603 { 604 int dir; 605 const union acpi_object *fields; 606 struct acpi_device *r_adev; 607 struct device *rdev; 608 609 if (link->type != ACPI_TYPE_PACKAGE || 610 link->package.count != 4) 611 return -EINVAL; 612 613 fields = link->package.elements; 614 615 if (fields[0].type != ACPI_TYPE_INTEGER || 616 fields[1].type != ACPI_TYPE_INTEGER || 617 fields[2].type != ACPI_TYPE_LOCAL_REFERENCE || 618 fields[3].type != ACPI_TYPE_INTEGER) 619 return -EINVAL; 620 621 r_adev = acpi_fetch_acpi_dev(fields[2].reference.handle); 622 if (!r_adev) 623 return -ENODEV; 624 625 dir = fields[3].integer.value; 626 if (dir == ACPI_CORESIGHT_LINK_MASTER) { 627 conn->src_port = fields[0].integer.value; 628 conn->dest_port = fields[1].integer.value; 629 rdev = coresight_find_device_by_fwnode(&r_adev->fwnode); 630 if (!rdev) 631 return -EPROBE_DEFER; 632 /* 633 * Hold the refcount to the target device. This could be 634 * released via: 635 * 1) coresight_release_platform_data() if the probe fails or 636 * this device is unregistered. 637 * 2) While removing the target device via 638 * coresight_remove_match(). 639 */ 640 conn->dest_fwnode = fwnode_handle_get(&r_adev->fwnode); 641 } else if (dir == ACPI_CORESIGHT_LINK_SLAVE) { 642 /* 643 * We are only interested in the port number 644 * for the input ports at this component. 645 * Store the port number in child_port. 646 */ 647 conn->dest_port = fields[0].integer.value; 648 } else { 649 /* Invalid direction */ 650 return -EINVAL; 651 } 652 653 return dir; 654 } 655 656 /* 657 * acpi_coresight_parse_graph - Parse the _DSD CoreSight graph 658 * connection information and populate the supplied coresight_platform_data 659 * instance. 660 */ 661 static int acpi_coresight_parse_graph(struct device *dev, 662 struct acpi_device *adev, 663 struct coresight_platform_data *pdata) 664 { 665 int ret = 0; 666 int i, nlinks; 667 const union acpi_object *graph; 668 struct coresight_connection conn, zero_conn = {}; 669 struct coresight_connection *new_conn; 670 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 671 672 graph = acpi_get_coresight_graph(adev, &buf); 673 /* 674 * There are no graph connections, which is fine for some components. 675 * e.g., ETE 676 */ 677 if (!graph) 678 goto free; 679 680 nlinks = graph->package.elements[2].integer.value; 681 if (!nlinks) 682 goto free; 683 684 for (i = 0; i < nlinks; i++) { 685 const union acpi_object *link = &graph->package.elements[3 + i]; 686 int dir; 687 688 conn = zero_conn; 689 dir = acpi_coresight_parse_link(adev, link, &conn); 690 if (dir < 0) { 691 ret = dir; 692 goto free; 693 } 694 695 if (dir == ACPI_CORESIGHT_LINK_MASTER) { 696 new_conn = coresight_add_out_conn(dev, pdata, &conn); 697 if (IS_ERR(new_conn)) { 698 ret = PTR_ERR(new_conn); 699 goto free; 700 } 701 } 702 } 703 704 free: 705 /* 706 * When ACPI fails to alloc a buffer, it will free the buffer 707 * created via ACPI_ALLOCATE_BUFFER and set to NULL. 708 * ACPI_FREE can handle NULL pointers, so free it directly. 709 */ 710 ACPI_FREE(buf.pointer); 711 return ret; 712 } 713 714 /* 715 * acpi_handle_to_logical_cpuid - Map a given acpi_handle to the 716 * logical CPU id of the corresponding CPU device. 717 * 718 * Returns the logical CPU id when found. Otherwise returns >= nr_cpus_id. 719 */ 720 static int 721 acpi_handle_to_logical_cpuid(acpi_handle handle) 722 { 723 int i; 724 struct acpi_processor *pr; 725 726 for_each_possible_cpu(i) { 727 pr = per_cpu(processors, i); 728 if (pr && pr->handle == handle) 729 break; 730 } 731 732 return i; 733 } 734 735 /* 736 * acpi_coresigh_get_cpu - Find the logical CPU id of the CPU associated 737 * with this coresight device. With ACPI bindings, the CoreSight components 738 * are listed as child device of the associated CPU. 739 * 740 * Returns the logical CPU id when found. Otherwise returns 0. 741 */ 742 static int acpi_coresight_get_cpu(struct device *dev) 743 { 744 int cpu; 745 acpi_handle cpu_handle; 746 acpi_status status; 747 struct acpi_device *adev = ACPI_COMPANION(dev); 748 749 if (!adev) 750 return -ENODEV; 751 status = acpi_get_parent(adev->handle, &cpu_handle); 752 if (ACPI_FAILURE(status)) 753 return -ENODEV; 754 755 cpu = acpi_handle_to_logical_cpuid(cpu_handle); 756 if (cpu >= nr_cpu_ids) 757 return -ENODEV; 758 return cpu; 759 } 760 761 static int 762 acpi_get_coresight_platform_data(struct device *dev, 763 struct coresight_platform_data *pdata) 764 { 765 struct acpi_device *adev; 766 767 adev = ACPI_COMPANION(dev); 768 if (!adev) 769 return -EINVAL; 770 771 return acpi_coresight_parse_graph(dev, adev, pdata); 772 } 773 774 #else 775 776 static inline int 777 acpi_get_coresight_platform_data(struct device *dev, 778 struct coresight_platform_data *pdata) 779 { 780 return -ENOENT; 781 } 782 783 static inline int acpi_coresight_get_cpu(struct device *dev) 784 { 785 return -ENODEV; 786 } 787 #endif 788 789 int coresight_get_cpu(struct device *dev) 790 { 791 if (is_of_node(dev->fwnode)) 792 return of_coresight_get_cpu(dev); 793 else if (is_acpi_device_node(dev->fwnode)) 794 return acpi_coresight_get_cpu(dev); 795 return 0; 796 } 797 EXPORT_SYMBOL_GPL(coresight_get_cpu); 798 799 struct coresight_platform_data * 800 coresight_get_platform_data(struct device *dev) 801 { 802 int ret = -ENOENT; 803 struct coresight_platform_data *pdata = NULL; 804 struct fwnode_handle *fwnode = dev_fwnode(dev); 805 806 if (IS_ERR_OR_NULL(fwnode)) 807 goto error; 808 809 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 810 if (!pdata) { 811 ret = -ENOMEM; 812 goto error; 813 } 814 815 if (is_of_node(fwnode)) 816 ret = of_get_coresight_platform_data(dev, pdata); 817 else if (is_acpi_device_node(fwnode)) 818 ret = acpi_get_coresight_platform_data(dev, pdata); 819 820 if (!ret) 821 return pdata; 822 error: 823 if (!IS_ERR_OR_NULL(pdata)) 824 /* Cleanup the connection information */ 825 coresight_release_platform_data(NULL, dev, pdata); 826 return ERR_PTR(ret); 827 } 828 EXPORT_SYMBOL_GPL(coresight_get_platform_data); 829