|
@@ -45,13 +45,13 @@ of_coresight_get_endpoint_device(struct device_node *endpoint)
|
|
endpoint, of_dev_node_match);
|
|
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");
|
|
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;
|
|
struct device_node *ep = NULL;
|
|
int in = 0, out = 0;
|
|
int in = 0, out = 0;
|
|
@@ -61,7 +61,7 @@ static void of_coresight_get_ports(const struct device_node *node,
|
|
if (!ep)
|
|
if (!ep)
|
|
break;
|
|
break;
|
|
|
|
|
|
- if (of_coresight_ep_is_input(ep))
|
|
|
|
|
|
+ if (of_coresight_legacy_ep_is_input(ep))
|
|
in++;
|
|
in++;
|
|
else
|
|
else
|
|
out++;
|
|
out++;
|
|
@@ -72,6 +72,67 @@ static void of_coresight_get_ports(const struct device_node *node,
|
|
*nr_outport = out;
|
|
*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,
|
|
static int of_coresight_alloc_memory(struct device *dev,
|
|
struct coresight_platform_data *pdata)
|
|
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);
|
|
rep = of_graph_get_remote_endpoint(ep);
|
|
if (!rep)
|
|
if (!rep)
|
|
break;
|
|
break;
|
|
- rparent = of_graph_get_port_parent(rep);
|
|
|
|
|
|
+ rparent = of_coresight_get_port_parent(rep);
|
|
if (!rparent)
|
|
if (!rparent)
|
|
break;
|
|
break;
|
|
if (of_graph_parse_endpoint(rep, &rendpoint))
|
|
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_platform_data *pdata;
|
|
struct coresight_connection *conn;
|
|
struct coresight_connection *conn;
|
|
struct device_node *ep = NULL;
|
|
struct device_node *ep = NULL;
|
|
|
|
+ const struct device_node *parent = NULL;
|
|
|
|
+ bool legacy_binding = false;
|
|
|
|
|
|
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
|
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
|
if (!pdata)
|
|
if (!pdata)
|
|
@@ -196,14 +259,29 @@ of_get_coresight_platform_data(struct device *dev,
|
|
if (ret)
|
|
if (ret)
|
|
return ERR_PTR(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;
|
|
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;
|
|
continue;
|
|
|
|
|
|
ret = of_coresight_parse_endpoint(dev, ep, conn);
|
|
ret = of_coresight_parse_endpoint(dev, ep, conn);
|