summaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing
diff options
context:
space:
mode:
authorSuzuki K Poulose <suzuki.poulose@arm.com>2018-09-20 21:17:43 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-25 20:09:17 +0200
commit5ecc7120194c6f10c09197e368b378c699100123 (patch)
treeb00f521d232b0c0bb5c91c2ed3da5d9c42435988 /drivers/hwtracing
parentcoresight: platform: Cleanup coresight connection handling (diff)
downloadlinux-5ecc7120194c6f10c09197e368b378c699100123.tar.xz
linux-5ecc7120194c6f10c09197e368b378c699100123.zip
coresight: Cleanup coresight DT bindings
The coresight drivers relied on default bindings for graph in DT, while reusing the "reg" field of the "ports" to indicate the actual hardware port number for the connections. This can cause duplicate ports with same addresses, but different direction. However, with the rules getting stricter for the address mismatch with the label, it is no longer possible to use the port address field for the hardware port number. This patch introduces new DT binding rules for coresight components, based on the same generic DT graph bindings, but avoiding the address duplication. - All output ports must be specified under a child node with name "out-ports". - All input ports must be specified under a childe node with name "in-ports". - Port address should match the hardware port number. The support for legacy bindings is retained, with a warning. Cc: Sudeep Holla <sudeep.holla@arm.com> Cc: Rob Herring <robh@kernel.org> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r--drivers/hwtracing/coresight/of_coresight.c98
1 files changed, 88 insertions, 10 deletions
diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c
index e8fb4e124744..da71c975e3f7 100644
--- a/drivers/hwtracing/coresight/of_coresight.c
+++ b/drivers/hwtracing/coresight/of_coresight.c
@@ -45,13 +45,13 @@ of_coresight_get_endpoint_device(struct device_node *endpoint)
endpoint, of_dev_node_match);
}
-static inline bool of_coresight_ep_is_input(struct device_node *ep)
+static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
{
return of_property_read_bool(ep, "slave-mode");
}
-static void of_coresight_get_ports(const struct device_node *node,
- int *nr_inport, int *nr_outport)
+static void of_coresight_get_ports_legacy(const struct device_node *node,
+ int *nr_inport, int *nr_outport)
{
struct device_node *ep = NULL;
int in = 0, out = 0;
@@ -61,7 +61,7 @@ static void of_coresight_get_ports(const struct device_node *node,
if (!ep)
break;
- if (of_coresight_ep_is_input(ep))
+ if (of_coresight_legacy_ep_is_input(ep))
in++;
else
out++;
@@ -72,6 +72,67 @@ static void of_coresight_get_ports(const struct device_node *node,
*nr_outport = out;
}
+static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
+{
+ struct device_node *parent = of_graph_get_port_parent(ep);
+
+ /*
+ * Skip one-level up to the real device node, if we
+ * are using the new bindings.
+ */
+ if (!of_node_cmp(parent->name, "in-ports") ||
+ !of_node_cmp(parent->name, "out-ports"))
+ parent = of_get_next_parent(parent);
+
+ return parent;
+}
+
+static inline struct device_node *
+of_coresight_get_input_ports_node(const struct device_node *node)
+{
+ return of_get_child_by_name(node, "in-ports");
+}
+
+static inline struct device_node *
+of_coresight_get_output_ports_node(const struct device_node *node)
+{
+ return of_get_child_by_name(node, "out-ports");
+}
+
+static inline int
+of_coresight_count_ports(struct device_node *port_parent)
+{
+ int i = 0;
+ struct device_node *ep = NULL;
+
+ while ((ep = of_graph_get_next_endpoint(port_parent, ep)))
+ i++;
+ return i;
+}
+
+static void of_coresight_get_ports(const struct device_node *node,
+ int *nr_inport, int *nr_outport)
+{
+ struct device_node *input_ports = NULL, *output_ports = NULL;
+
+ input_ports = of_coresight_get_input_ports_node(node);
+ output_ports = of_coresight_get_output_ports_node(node);
+
+ if (input_ports || output_ports) {
+ if (input_ports) {
+ *nr_inport = of_coresight_count_ports(input_ports);
+ of_node_put(input_ports);
+ }
+ if (output_ports) {
+ *nr_outport = of_coresight_count_ports(output_ports);
+ of_node_put(output_ports);
+ }
+ } else {
+ /* Fall back to legacy DT bindings parsing */
+ of_coresight_get_ports_legacy(node, nr_inport, nr_outport);
+ }
+}
+
static int of_coresight_alloc_memory(struct device *dev,
struct coresight_platform_data *pdata)
{
@@ -136,7 +197,7 @@ static int of_coresight_parse_endpoint(struct device *dev,
rep = of_graph_get_remote_endpoint(ep);
if (!rep)
break;
- rparent = of_graph_get_port_parent(rep);
+ rparent = of_coresight_get_port_parent(rep);
if (!rparent)
break;
if (of_graph_parse_endpoint(rep, &rendpoint))
@@ -176,6 +237,8 @@ of_get_coresight_platform_data(struct device *dev,
struct coresight_platform_data *pdata;
struct coresight_connection *conn;
struct device_node *ep = NULL;
+ const struct device_node *parent = NULL;
+ bool legacy_binding = false;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
@@ -196,14 +259,29 @@ of_get_coresight_platform_data(struct device *dev,
if (ret)
return ERR_PTR(ret);
+ parent = of_coresight_get_output_ports_node(node);
+ /*
+ * If the DT uses obsoleted bindings, the ports are listed
+ * under the device and we need to filter out the input
+ * ports.
+ */
+ if (!parent) {
+ legacy_binding = true;
+ parent = node;
+ dev_warn_once(dev, "Uses obsolete Coresight DT bindings\n");
+ }
+
conn = pdata->conns;
- /* Iterate through each port to discover topology */
- while ((ep = of_graph_get_next_endpoint(node, ep))) {
+
+ /* Iterate through each output port to discover topology */
+ while ((ep = of_graph_get_next_endpoint(parent, ep))) {
/*
- * No need to deal with input ports, as processing the
- * output ports connected to them will process the details.
+ * Legacy binding mixes input/output ports under the
+ * same parent. So, skip the input ports if we are dealing
+ * with legacy binding, as they processed with their
+ * connected output ports.
*/
- if (of_coresight_ep_is_input(ep))
+ if (legacy_binding && of_coresight_legacy_ep_is_input(ep))
continue;
ret = of_coresight_parse_endpoint(dev, ep, conn);