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