Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2012, The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/acpi.h>
0007 #include <linux/types.h>
0008 #include <linux/err.h>
0009 #include <linux/slab.h>
0010 #include <linux/clk.h>
0011 #include <linux/of.h>
0012 #include <linux/of_address.h>
0013 #include <linux/of_graph.h>
0014 #include <linux/of_platform.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/amba/bus.h>
0017 #include <linux/coresight.h>
0018 #include <linux/cpumask.h>
0019 #include <asm/smp_plat.h>
0020 
0021 #include "coresight-priv.h"
0022 /*
0023  * coresight_alloc_conns: Allocate connections record for each output
0024  * port from the device.
0025  */
0026 static int coresight_alloc_conns(struct device *dev,
0027                  struct coresight_platform_data *pdata)
0028 {
0029     if (pdata->nr_outport) {
0030         pdata->conns = devm_kcalloc(dev, pdata->nr_outport,
0031                         sizeof(*pdata->conns), GFP_KERNEL);
0032         if (!pdata->conns)
0033             return -ENOMEM;
0034     }
0035 
0036     return 0;
0037 }
0038 
0039 static struct device *
0040 coresight_find_device_by_fwnode(struct fwnode_handle *fwnode)
0041 {
0042     struct device *dev = NULL;
0043 
0044     /*
0045      * If we have a non-configurable replicator, it will be found on the
0046      * platform bus.
0047      */
0048     dev = bus_find_device_by_fwnode(&platform_bus_type, fwnode);
0049     if (dev)
0050         return dev;
0051 
0052     /*
0053      * We have a configurable component - circle through the AMBA bus
0054      * looking for the device that matches the endpoint node.
0055      */
0056     return bus_find_device_by_fwnode(&amba_bustype, fwnode);
0057 }
0058 
0059 /*
0060  * Find a registered coresight device from a device fwnode.
0061  * The node info is associated with the AMBA parent, but the
0062  * csdev keeps a copy so iterate round the coresight bus to
0063  * find the device.
0064  */
0065 struct coresight_device *
0066 coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
0067 {
0068     struct device *dev;
0069     struct coresight_device *csdev = NULL;
0070 
0071     dev = bus_find_device_by_fwnode(&coresight_bustype, r_fwnode);
0072     if (dev) {
0073         csdev = to_coresight_device(dev);
0074         put_device(dev);
0075     }
0076     return csdev;
0077 }
0078 EXPORT_SYMBOL_GPL(coresight_find_csdev_by_fwnode);
0079 
0080 #ifdef CONFIG_OF
0081 static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
0082 {
0083     return of_property_read_bool(ep, "slave-mode");
0084 }
0085 
0086 static void of_coresight_get_ports_legacy(const struct device_node *node,
0087                       int *nr_inport, int *nr_outport)
0088 {
0089     struct device_node *ep = NULL;
0090     struct of_endpoint endpoint;
0091     int in = 0, out = 0;
0092 
0093     /*
0094      * Avoid warnings in of_graph_get_next_endpoint()
0095      * if the device doesn't have any graph connections
0096      */
0097     if (!of_graph_is_present(node))
0098         return;
0099     do {
0100         ep = of_graph_get_next_endpoint(node, ep);
0101         if (!ep)
0102             break;
0103 
0104         if (of_graph_parse_endpoint(ep, &endpoint))
0105             continue;
0106 
0107         if (of_coresight_legacy_ep_is_input(ep)) {
0108             in = (endpoint.port + 1 > in) ?
0109                 endpoint.port + 1 : in;
0110         } else {
0111             out = (endpoint.port + 1) > out ?
0112                 endpoint.port + 1 : out;
0113         }
0114 
0115     } while (ep);
0116 
0117     *nr_inport = in;
0118     *nr_outport = out;
0119 }
0120 
0121 static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
0122 {
0123     struct device_node *parent = of_graph_get_port_parent(ep);
0124 
0125     /*
0126      * Skip one-level up to the real device node, if we
0127      * are using the new bindings.
0128      */
0129     if (of_node_name_eq(parent, "in-ports") ||
0130         of_node_name_eq(parent, "out-ports"))
0131         parent = of_get_next_parent(parent);
0132 
0133     return parent;
0134 }
0135 
0136 static inline struct device_node *
0137 of_coresight_get_input_ports_node(const struct device_node *node)
0138 {
0139     return of_get_child_by_name(node, "in-ports");
0140 }
0141 
0142 static inline struct device_node *
0143 of_coresight_get_output_ports_node(const struct device_node *node)
0144 {
0145     return of_get_child_by_name(node, "out-ports");
0146 }
0147 
0148 static inline int
0149 of_coresight_count_ports(struct device_node *port_parent)
0150 {
0151     int i = 0;
0152     struct device_node *ep = NULL;
0153     struct of_endpoint endpoint;
0154 
0155     while ((ep = of_graph_get_next_endpoint(port_parent, ep))) {
0156         /* Defer error handling to parsing */
0157         if (of_graph_parse_endpoint(ep, &endpoint))
0158             continue;
0159         if (endpoint.port + 1 > i)
0160             i = endpoint.port + 1;
0161     }
0162 
0163     return i;
0164 }
0165 
0166 static void of_coresight_get_ports(const struct device_node *node,
0167                    int *nr_inport, int *nr_outport)
0168 {
0169     struct device_node *input_ports = NULL, *output_ports = NULL;
0170 
0171     input_ports = of_coresight_get_input_ports_node(node);
0172     output_ports = of_coresight_get_output_ports_node(node);
0173 
0174     if (input_ports || output_ports) {
0175         if (input_ports) {
0176             *nr_inport = of_coresight_count_ports(input_ports);
0177             of_node_put(input_ports);
0178         }
0179         if (output_ports) {
0180             *nr_outport = of_coresight_count_ports(output_ports);
0181             of_node_put(output_ports);
0182         }
0183     } else {
0184         /* Fall back to legacy DT bindings parsing */
0185         of_coresight_get_ports_legacy(node, nr_inport, nr_outport);
0186     }
0187 }
0188 
0189 static int of_coresight_get_cpu(struct device *dev)
0190 {
0191     int cpu;
0192     struct device_node *dn;
0193 
0194     if (!dev->of_node)
0195         return -ENODEV;
0196 
0197     dn = of_parse_phandle(dev->of_node, "cpu", 0);
0198     if (!dn)
0199         return -ENODEV;
0200 
0201     cpu = of_cpu_node_to_id(dn);
0202     of_node_put(dn);
0203 
0204     return cpu;
0205 }
0206 
0207 /*
0208  * of_coresight_parse_endpoint : Parse the given output endpoint @ep
0209  * and fill the connection information in @conn
0210  *
0211  * Parses the local port, remote device name and the remote port.
0212  *
0213  * Returns :
0214  *   0  - If the parsing completed without any fatal errors.
0215  *  -Errno  - Fatal error, abort the scanning.
0216  */
0217 static int of_coresight_parse_endpoint(struct device *dev,
0218                        struct device_node *ep,
0219                        struct coresight_platform_data *pdata)
0220 {
0221     int ret = 0;
0222     struct of_endpoint endpoint, rendpoint;
0223     struct device_node *rparent = NULL;
0224     struct device_node *rep = NULL;
0225     struct device *rdev = NULL;
0226     struct fwnode_handle *rdev_fwnode;
0227     struct coresight_connection *conn;
0228 
0229     do {
0230         /* Parse the local port details */
0231         if (of_graph_parse_endpoint(ep, &endpoint))
0232             break;
0233         /*
0234          * Get a handle on the remote endpoint and the device it is
0235          * attached to.
0236          */
0237         rep = of_graph_get_remote_endpoint(ep);
0238         if (!rep)
0239             break;
0240         rparent = of_coresight_get_port_parent(rep);
0241         if (!rparent)
0242             break;
0243         if (of_graph_parse_endpoint(rep, &rendpoint))
0244             break;
0245 
0246         rdev_fwnode = of_fwnode_handle(rparent);
0247         /* If the remote device is not available, defer probing */
0248         rdev = coresight_find_device_by_fwnode(rdev_fwnode);
0249         if (!rdev) {
0250             ret = -EPROBE_DEFER;
0251             break;
0252         }
0253 
0254         conn = &pdata->conns[endpoint.port];
0255         if (conn->child_fwnode) {
0256             dev_warn(dev, "Duplicate output port %d\n",
0257                  endpoint.port);
0258             ret = -EINVAL;
0259             break;
0260         }
0261         conn->outport = endpoint.port;
0262         /*
0263          * Hold the refcount to the target device. This could be
0264          * released via:
0265          * 1) coresight_release_platform_data() if the probe fails or
0266          *    this device is unregistered.
0267          * 2) While removing the target device via
0268          *    coresight_remove_match()
0269          */
0270         conn->child_fwnode = fwnode_handle_get(rdev_fwnode);
0271         conn->child_port = rendpoint.port;
0272         /* Connection record updated */
0273     } while (0);
0274 
0275     of_node_put(rparent);
0276     of_node_put(rep);
0277     put_device(rdev);
0278 
0279     return ret;
0280 }
0281 
0282 static int of_get_coresight_platform_data(struct device *dev,
0283                       struct coresight_platform_data *pdata)
0284 {
0285     int ret = 0;
0286     struct device_node *ep = NULL;
0287     const struct device_node *parent = NULL;
0288     bool legacy_binding = false;
0289     struct device_node *node = dev->of_node;
0290 
0291     /* Get the number of input and output port for this component */
0292     of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);
0293 
0294     /* If there are no output connections, we are done */
0295     if (!pdata->nr_outport)
0296         return 0;
0297 
0298     ret = coresight_alloc_conns(dev, pdata);
0299     if (ret)
0300         return ret;
0301 
0302     parent = of_coresight_get_output_ports_node(node);
0303     /*
0304      * If the DT uses obsoleted bindings, the ports are listed
0305      * under the device and we need to filter out the input
0306      * ports.
0307      */
0308     if (!parent) {
0309         legacy_binding = true;
0310         parent = node;
0311         dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n");
0312     }
0313 
0314     /* Iterate through each output port to discover topology */
0315     while ((ep = of_graph_get_next_endpoint(parent, ep))) {
0316         /*
0317          * Legacy binding mixes input/output ports under the
0318          * same parent. So, skip the input ports if we are dealing
0319          * with legacy binding, as they processed with their
0320          * connected output ports.
0321          */
0322         if (legacy_binding && of_coresight_legacy_ep_is_input(ep))
0323             continue;
0324 
0325         ret = of_coresight_parse_endpoint(dev, ep, pdata);
0326         if (ret)
0327             return ret;
0328     }
0329 
0330     return 0;
0331 }
0332 #else
0333 static inline int
0334 of_get_coresight_platform_data(struct device *dev,
0335                    struct coresight_platform_data *pdata)
0336 {
0337     return -ENOENT;
0338 }
0339 
0340 static inline int of_coresight_get_cpu(struct device *dev)
0341 {
0342     return -ENODEV;
0343 }
0344 #endif
0345 
0346 #ifdef CONFIG_ACPI
0347 
0348 #include <acpi/actypes.h>
0349 #include <acpi/processor.h>
0350 
0351 /* ACPI Graph _DSD UUID : "ab02a46b-74c7-45a2-bd68-f7d344ef2153" */
0352 static const guid_t acpi_graph_uuid = GUID_INIT(0xab02a46b, 0x74c7, 0x45a2,
0353                         0xbd, 0x68, 0xf7, 0xd3,
0354                         0x44, 0xef, 0x21, 0x53);
0355 /* Coresight ACPI Graph UUID : "3ecbc8b6-1d0e-4fb3-8107-e627f805c6cd" */
0356 static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3,
0357                              0x81, 0x07, 0xe6, 0x27,
0358                              0xf8, 0x05, 0xc6, 0xcd);
0359 #define ACPI_CORESIGHT_LINK_SLAVE   0
0360 #define ACPI_CORESIGHT_LINK_MASTER  1
0361 
0362 static inline bool is_acpi_guid(const union acpi_object *obj)
0363 {
0364     return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16);
0365 }
0366 
0367 /*
0368  * acpi_guid_matches    - Checks if the given object is a GUID object and
0369  * that it matches the supplied the GUID.
0370  */
0371 static inline bool acpi_guid_matches(const union acpi_object *obj,
0372                    const guid_t *guid)
0373 {
0374     return is_acpi_guid(obj) &&
0375            guid_equal((guid_t *)obj->buffer.pointer, guid);
0376 }
0377 
0378 static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
0379 {
0380     return acpi_guid_matches(obj, &acpi_graph_uuid);
0381 }
0382 
0383 static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
0384 {
0385     return acpi_guid_matches(obj, &coresight_graph_uuid);
0386 }
0387 
0388 static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
0389 {
0390     const union acpi_object *graphid, *guid, *links;
0391 
0392     if (obj->type != ACPI_TYPE_PACKAGE ||
0393         obj->package.count < 3)
0394         return false;
0395 
0396     graphid = &obj->package.elements[0];
0397     guid = &obj->package.elements[1];
0398     links = &obj->package.elements[2];
0399 
0400     if (graphid->type != ACPI_TYPE_INTEGER ||
0401         links->type != ACPI_TYPE_INTEGER)
0402         return false;
0403 
0404     return is_acpi_coresight_graph_guid(guid);
0405 }
0406 
0407 /*
0408  * acpi_validate_dsd_graph  - Make sure the given _DSD graph conforms
0409  * to the ACPI _DSD Graph specification.
0410  *
0411  * ACPI Devices Graph property has the following format:
0412  *  {
0413  *  Revision    - Integer, must be 0
0414  *  NumberOfGraphs  - Integer, N indicating the following list.
0415  *  Graph[1],
0416  *   ...
0417  *  Graph[N]
0418  *  }
0419  *
0420  * And each Graph entry has the following format:
0421  *  {
0422  *  GraphID     - Integer, identifying a graph the device belongs to.
0423  *  UUID        - UUID identifying the specification that governs
0424  *            this graph. (e.g, see is_acpi_coresight_graph())
0425  *  NumberOfLinks   - Number "N" of connections on this node of the graph.
0426  *  Links[1]
0427  *  ...
0428  *  Links[N]
0429  *  }
0430  *
0431  * Where each "Links" entry has the following format:
0432  *
0433  * {
0434  *  SourcePortAddress   - Integer
0435  *  DestinationPortAddress  - Integer
0436  *  DestinationDeviceName   - Reference to another device
0437  *  ( --- CoreSight specific extensions below ---)
0438  *  DirectionOfFlow     - Integer 1 for output(master)
0439  *                0 for input(slave)
0440  * }
0441  *
0442  * e.g:
0443  * For a Funnel device
0444  *
0445  * Device(MFUN) {
0446  *   ...
0447  *
0448  *   Name (_DSD, Package() {
0449  *  // DSD Package contains tuples of {  Proeprty_Type_UUID, Package() }
0450  *  ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), //Std. Property UUID
0451  *  Package() {
0452  *      Package(2) { "property-name", <property-value> }
0453  *  },
0454  *
0455  *  ToUUID("ab02a46b-74c7-45a2-bd68-f7d344ef2153"), // ACPI Graph UUID
0456  *  Package() {
0457  *    0,        // Revision
0458  *    1,        // NumberOfGraphs.
0459  *    Package() {   // Graph[0] Package
0460  *       1,     // GraphID
0461  *       // Coresight Graph UUID
0462  *       ToUUID("3ecbc8b6-1d0e-4fb3-8107-e627f805c6cd"),
0463  *       3,     // NumberOfLinks aka ports
0464  *       // Link[0]: Output_0 -> Replicator:Input_0
0465  *       Package () { 0, 0, \_SB_.RPL0, 1 },
0466  *       // Link[1]: Input_0 <- Cluster0_Funnel0:Output_0
0467  *       Package () { 0, 0, \_SB_.CLU0.FUN0, 0 },
0468  *       // Link[2]: Input_1 <- Cluster1_Funnel0:Output_0
0469  *        Package () { 1, 0, \_SB_.CLU1.FUN0, 0 },
0470  *    } // End of Graph[0] Package
0471  *
0472  *  }, // End of ACPI Graph Property
0473  *  })
0474  */
0475 static inline bool acpi_validate_dsd_graph(const union acpi_object *graph)
0476 {
0477     int i, n;
0478     const union acpi_object *rev, *nr_graphs;
0479 
0480     /* The graph must contain at least the Revision and Number of Graphs */
0481     if (graph->package.count < 2)
0482         return false;
0483 
0484     rev = &graph->package.elements[0];
0485     nr_graphs = &graph->package.elements[1];
0486 
0487     if (rev->type != ACPI_TYPE_INTEGER ||
0488         nr_graphs->type != ACPI_TYPE_INTEGER)
0489         return false;
0490 
0491     /* We only support revision 0 */
0492     if (rev->integer.value != 0)
0493         return false;
0494 
0495     n = nr_graphs->integer.value;
0496     /* CoreSight devices are only part of a single Graph */
0497     if (n != 1)
0498         return false;
0499 
0500     /* Make sure the ACPI graph package has right number of elements */
0501     if (graph->package.count != (n + 2))
0502         return false;
0503 
0504     /*
0505      * Each entry must be a graph package with at least 3 members :
0506      * { GraphID, UUID, NumberOfLinks(n), Links[.],... }
0507      */
0508     for (i = 2; i < n + 2; i++) {
0509         const union acpi_object *obj = &graph->package.elements[i];
0510 
0511         if (obj->type != ACPI_TYPE_PACKAGE ||
0512             obj->package.count < 3)
0513             return false;
0514     }
0515 
0516     return true;
0517 }
0518 
0519 /* acpi_get_dsd_graph   - Find the _DSD Graph property for the given device. */
0520 static const union acpi_object *
0521 acpi_get_dsd_graph(struct acpi_device *adev)
0522 {
0523     int i;
0524     struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
0525     acpi_status status;
0526     const union acpi_object *dsd;
0527 
0528     status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL,
0529                         &buf, ACPI_TYPE_PACKAGE);
0530     if (ACPI_FAILURE(status))
0531         return NULL;
0532 
0533     dsd = buf.pointer;
0534 
0535     /*
0536      * _DSD property consists tuples { Prop_UUID, Package() }
0537      * Iterate through all the packages and find the Graph.
0538      */
0539     for (i = 0; i + 1 < dsd->package.count; i += 2) {
0540         const union acpi_object *guid, *package;
0541 
0542         guid = &dsd->package.elements[i];
0543         package = &dsd->package.elements[i + 1];
0544 
0545         /* All _DSD elements must have a UUID and a Package */
0546         if (!is_acpi_guid(guid) || package->type != ACPI_TYPE_PACKAGE)
0547             break;
0548         /* Skip the non-Graph _DSD packages */
0549         if (!is_acpi_dsd_graph_guid(guid))
0550             continue;
0551         if (acpi_validate_dsd_graph(package))
0552             return package;
0553         /* Invalid graph format, continue */
0554         dev_warn(&adev->dev, "Invalid Graph _DSD property\n");
0555     }
0556 
0557     return NULL;
0558 }
0559 
0560 static inline bool
0561 acpi_validate_coresight_graph(const union acpi_object *cs_graph)
0562 {
0563     int nlinks;
0564 
0565     nlinks = cs_graph->package.elements[2].integer.value;
0566     /*
0567      * Graph must have the following fields :
0568      * { GraphID, GraphUUID, NumberOfLinks, Links... }
0569      */
0570     if (cs_graph->package.count != (nlinks + 3))
0571         return false;
0572     /* The links are validated in acpi_coresight_parse_link() */
0573     return true;
0574 }
0575 
0576 /*
0577  * acpi_get_coresight_graph - Parse the device _DSD tables and find
0578  * the Graph property matching the CoreSight Graphs.
0579  *
0580  * Returns the pointer to the CoreSight Graph Package when found. Otherwise
0581  * returns NULL.
0582  */
0583 static const union acpi_object *
0584 acpi_get_coresight_graph(struct acpi_device *adev)
0585 {
0586     const union acpi_object *graph_list, *graph;
0587     int i, nr_graphs;
0588 
0589     graph_list = acpi_get_dsd_graph(adev);
0590     if (!graph_list)
0591         return graph_list;
0592 
0593     nr_graphs = graph_list->package.elements[1].integer.value;
0594 
0595     for (i = 2; i < nr_graphs + 2; i++) {
0596         graph = &graph_list->package.elements[i];
0597         if (!is_acpi_coresight_graph(graph))
0598             continue;
0599         if (acpi_validate_coresight_graph(graph))
0600             return graph;
0601         /* Invalid graph format */
0602         break;
0603     }
0604 
0605     return NULL;
0606 }
0607 
0608 /*
0609  * acpi_coresight_parse_link    - Parse the given Graph connection
0610  * of the device and populate the coresight_connection for an output
0611  * connection.
0612  *
0613  * CoreSight Graph specification mandates that the direction of the data
0614  * flow must be specified in the link. i.e,
0615  *
0616  *  SourcePortAddress,  // Integer
0617  *  DestinationPortAddress, // Integer
0618  *  DestinationDeviceName,  // Reference to another device
0619  *  DirectionOfFlow,    // 1 for output(master), 0 for input(slave)
0620  *
0621  * Returns the direction of the data flow [ Input(slave) or Output(master) ]
0622  * upon success.
0623  * Returns an negative error number otherwise.
0624  */
0625 static int acpi_coresight_parse_link(struct acpi_device *adev,
0626                      const union acpi_object *link,
0627                      struct coresight_connection *conn)
0628 {
0629     int dir;
0630     const union acpi_object *fields;
0631     struct acpi_device *r_adev;
0632     struct device *rdev;
0633 
0634     if (link->type != ACPI_TYPE_PACKAGE ||
0635         link->package.count != 4)
0636         return -EINVAL;
0637 
0638     fields = link->package.elements;
0639 
0640     if (fields[0].type != ACPI_TYPE_INTEGER ||
0641         fields[1].type != ACPI_TYPE_INTEGER ||
0642         fields[2].type != ACPI_TYPE_LOCAL_REFERENCE ||
0643         fields[3].type != ACPI_TYPE_INTEGER)
0644         return -EINVAL;
0645 
0646     r_adev = acpi_fetch_acpi_dev(fields[2].reference.handle);
0647     if (!r_adev)
0648         return -ENODEV;
0649 
0650     dir = fields[3].integer.value;
0651     if (dir == ACPI_CORESIGHT_LINK_MASTER) {
0652         conn->outport = fields[0].integer.value;
0653         conn->child_port = fields[1].integer.value;
0654         rdev = coresight_find_device_by_fwnode(&r_adev->fwnode);
0655         if (!rdev)
0656             return -EPROBE_DEFER;
0657         /*
0658          * Hold the refcount to the target device. This could be
0659          * released via:
0660          * 1) coresight_release_platform_data() if the probe fails or
0661          *    this device is unregistered.
0662          * 2) While removing the target device via
0663          *    coresight_remove_match().
0664          */
0665         conn->child_fwnode = fwnode_handle_get(&r_adev->fwnode);
0666     } else if (dir == ACPI_CORESIGHT_LINK_SLAVE) {
0667         /*
0668          * We are only interested in the port number
0669          * for the input ports at this component.
0670          * Store the port number in child_port.
0671          */
0672         conn->child_port = fields[0].integer.value;
0673     } else {
0674         /* Invalid direction */
0675         return -EINVAL;
0676     }
0677 
0678     return dir;
0679 }
0680 
0681 /*
0682  * acpi_coresight_parse_graph   - Parse the _DSD CoreSight graph
0683  * connection information and populate the supplied coresight_platform_data
0684  * instance.
0685  */
0686 static int acpi_coresight_parse_graph(struct acpi_device *adev,
0687                       struct coresight_platform_data *pdata)
0688 {
0689     int rc, i, nlinks;
0690     const union acpi_object *graph;
0691     struct coresight_connection *conns, *ptr;
0692 
0693     pdata->nr_inport = pdata->nr_outport = 0;
0694     graph = acpi_get_coresight_graph(adev);
0695     if (!graph)
0696         return -ENOENT;
0697 
0698     nlinks = graph->package.elements[2].integer.value;
0699     if (!nlinks)
0700         return 0;
0701 
0702     /*
0703      * To avoid scanning the table twice (once for finding the number of
0704      * output links and then later for parsing the output links),
0705      * cache the links information in one go and then later copy
0706      * it to the pdata.
0707      */
0708     conns = devm_kcalloc(&adev->dev, nlinks, sizeof(*conns), GFP_KERNEL);
0709     if (!conns)
0710         return -ENOMEM;
0711     ptr = conns;
0712     for (i = 0; i < nlinks; i++) {
0713         const union acpi_object *link = &graph->package.elements[3 + i];
0714         int dir;
0715 
0716         dir = acpi_coresight_parse_link(adev, link, ptr);
0717         if (dir < 0)
0718             return dir;
0719 
0720         if (dir == ACPI_CORESIGHT_LINK_MASTER) {
0721             if (ptr->outport >= pdata->nr_outport)
0722                 pdata->nr_outport = ptr->outport + 1;
0723             ptr++;
0724         } else {
0725             WARN_ON(pdata->nr_inport == ptr->child_port + 1);
0726             /*
0727              * We do not track input port connections for a device.
0728              * However we need the highest port number described,
0729              * which can be recorded now and reuse this connection
0730              * record for an output connection. Hence, do not move
0731              * the ptr for input connections
0732              */
0733             if (ptr->child_port >= pdata->nr_inport)
0734                 pdata->nr_inport = ptr->child_port + 1;
0735         }
0736     }
0737 
0738     rc = coresight_alloc_conns(&adev->dev, pdata);
0739     if (rc)
0740         return rc;
0741 
0742     /* Copy the connection information to the final location */
0743     for (i = 0; conns + i < ptr; i++) {
0744         int port = conns[i].outport;
0745 
0746         /* Duplicate output port */
0747         WARN_ON(pdata->conns[port].child_fwnode);
0748         pdata->conns[port] = conns[i];
0749     }
0750 
0751     devm_kfree(&adev->dev, conns);
0752     return 0;
0753 }
0754 
0755 /*
0756  * acpi_handle_to_logical_cpuid - Map a given acpi_handle to the
0757  * logical CPU id of the corresponding CPU device.
0758  *
0759  * Returns the logical CPU id when found. Otherwise returns >= nr_cpus_id.
0760  */
0761 static int
0762 acpi_handle_to_logical_cpuid(acpi_handle handle)
0763 {
0764     int i;
0765     struct acpi_processor *pr;
0766 
0767     for_each_possible_cpu(i) {
0768         pr = per_cpu(processors, i);
0769         if (pr && pr->handle == handle)
0770             break;
0771     }
0772 
0773     return i;
0774 }
0775 
0776 /*
0777  * acpi_coresigh_get_cpu - Find the logical CPU id of the CPU associated
0778  * with this coresight device. With ACPI bindings, the CoreSight components
0779  * are listed as child device of the associated CPU.
0780  *
0781  * Returns the logical CPU id when found. Otherwise returns 0.
0782  */
0783 static int acpi_coresight_get_cpu(struct device *dev)
0784 {
0785     int cpu;
0786     acpi_handle cpu_handle;
0787     acpi_status status;
0788     struct acpi_device *adev = ACPI_COMPANION(dev);
0789 
0790     if (!adev)
0791         return -ENODEV;
0792     status = acpi_get_parent(adev->handle, &cpu_handle);
0793     if (ACPI_FAILURE(status))
0794         return -ENODEV;
0795 
0796     cpu = acpi_handle_to_logical_cpuid(cpu_handle);
0797     if (cpu >= nr_cpu_ids)
0798         return -ENODEV;
0799     return cpu;
0800 }
0801 
0802 static int
0803 acpi_get_coresight_platform_data(struct device *dev,
0804                  struct coresight_platform_data *pdata)
0805 {
0806     struct acpi_device *adev;
0807 
0808     adev = ACPI_COMPANION(dev);
0809     if (!adev)
0810         return -EINVAL;
0811 
0812     return acpi_coresight_parse_graph(adev, pdata);
0813 }
0814 
0815 #else
0816 
0817 static inline int
0818 acpi_get_coresight_platform_data(struct device *dev,
0819                  struct coresight_platform_data *pdata)
0820 {
0821     return -ENOENT;
0822 }
0823 
0824 static inline int acpi_coresight_get_cpu(struct device *dev)
0825 {
0826     return -ENODEV;
0827 }
0828 #endif
0829 
0830 int coresight_get_cpu(struct device *dev)
0831 {
0832     if (is_of_node(dev->fwnode))
0833         return of_coresight_get_cpu(dev);
0834     else if (is_acpi_device_node(dev->fwnode))
0835         return acpi_coresight_get_cpu(dev);
0836     return 0;
0837 }
0838 EXPORT_SYMBOL_GPL(coresight_get_cpu);
0839 
0840 struct coresight_platform_data *
0841 coresight_get_platform_data(struct device *dev)
0842 {
0843     int ret = -ENOENT;
0844     struct coresight_platform_data *pdata = NULL;
0845     struct fwnode_handle *fwnode = dev_fwnode(dev);
0846 
0847     if (IS_ERR_OR_NULL(fwnode))
0848         goto error;
0849 
0850     pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
0851     if (!pdata) {
0852         ret = -ENOMEM;
0853         goto error;
0854     }
0855 
0856     if (is_of_node(fwnode))
0857         ret = of_get_coresight_platform_data(dev, pdata);
0858     else if (is_acpi_device_node(fwnode))
0859         ret = acpi_get_coresight_platform_data(dev, pdata);
0860 
0861     if (!ret)
0862         return pdata;
0863 error:
0864     if (!IS_ERR_OR_NULL(pdata))
0865         /* Cleanup the connection information */
0866         coresight_release_platform_data(NULL, pdata);
0867     return ERR_PTR(ret);
0868 }
0869 EXPORT_SYMBOL_GPL(coresight_get_platform_data);