Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c881a3f authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "coresight: Add snapshot of Coresight cti driver"

parents 13879ddd c6996176
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -15,6 +15,15 @@ menuconfig CORESIGHT
	  trace source gets enabled.

if CORESIGHT
config CORESIGHT_QGKI
	bool "Enable coresight for QGKI or debug variant"
	depends on QGKI
	help
	  This enables CoreSight drivers with QGKI flag. When this flag is
	  enabled, it is safe to assume that the build is a Non GKI build.
	  It can be either QGKI build or a debug build. If this flag is
	  enabled, all the ABI compatibilities are not applicable.

config CORESIGHT_LINKS_AND_SINKS
	bool "CoreSight Link and Sink drivers"
	help
@@ -110,6 +119,69 @@ config CORESIGHT_CPU_DEBUG
	  properly, please refer Documentation/trace/coresight-cpu-debug.rst
	  for detailed description and the example for usage.

config CORESIGHT_CTI
	bool "CoreSight Cross Trigger Interface driver"
	help
	  This driver provides support for Cross Trigger Interface that is
	  used to input or output i.e. pass cross trigger events from one
	  hardware component to another. It can also be used to pass
	  software generated events.

config CORESIGHT_CTI_SAVE_DISABLE
	bool "Turn off CTI save and restore"
	depends on CORESIGHT_CTI
	help
	  Turns off CoreSight CTI save and restore support for cpu CTIs. This
	  avoids voting for the clocks during probe as well as the associated
	  save and restore latency at the cost of breaking cpu CTI support on
	  targets where cpu CTIs have to be preserved across power collapse.

	  If unsure, say 'N' here to avoid breaking cpu CTI support.

config CORESIGHT_TPDA
	bool "CoreSight Trace, Profiling & Diagnostics Aggregator driver"
	help
	  This driver provides support for configuring aggregator. This is
	  primarily useful for pulling the data sets from one or more
	  attached monitors and pushing the resultant data out. Multiple
	  monitors are connected on different input ports of TPDA.

config CORESIGHT_TPDM
	bool "CoreSight Trace, Profiling & Diagnostics Monitor driver"
	help
	  This driver provides support for configuring monitor. Monitors are
	  primarily responsible for data set collection and support the
	  ability to collect any permutation of data set types. Monitors are
	  also responsible for interaction with system cross triggering.

config CORESIGHT_TPDM_DEFAULT_ENABLE
	bool "Turn on TPDM tracing by default"
	depends on CORESIGHT_TPDM
	help
	  Turns on CoreSight TPDM tracing for different data set types by
	  default. Otherwise, tracing is disabled by default but can be
	  enabled via sysfs.

	  If unsure, say 'N' here to avoid potential power and performance
	  penalty.

config CORESIGHT_CSR
	bool "CoreSight Slave Register driver"
	help
	  This driver provides support for CoreSight Slave Register block
	  that hosts miscellaneous configuration registers.
	  Those configuration registers can be used to control, various
	  coresight configurations.

config CORESIGHT_HWEVENT
	bool "CoreSight Hardware Event driver"
	depends on CORESIGHT_STM
	select CORESIGHT_CSR
	help
	  This driver provides support for monitoring and tracing CoreSight
	  Hardware Event across STM interface. It configures Coresight
	  Hardware Event mux control registers to select hardware events
	  based on user input.
config CORESIGHT_TPDA
	bool "CoreSight Trace, Profiling & Diagnostics Aggregator driver"
	help
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \
obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o
obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o
obj-$(CONFIG_CORESIGHT_TPDM) += coresight-tpdm.o
obj-$(CONFIG_CORESIGHT_HWEVENT) += coresight-hwevent.o
+1566 −0

File added.

Preview size limit exceeded, changes collapsed.

+71 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012, 2019 The Linux Foundation. All rights reserved.
 */

#include <linux/acpi.h>
@@ -184,6 +184,9 @@ static int of_coresight_parse_endpoint(struct device *dev,
	struct of_endpoint endpoint, rendpoint;
	struct device_node *rparent = NULL;
	struct device_node *rep = NULL;
#ifdef CONFIG_CORESIGHT_QGKI
	struct device_node *sn = NULL;
#endif
	struct device *rdev = NULL;
	struct fwnode_handle *rdev_fwnode;

@@ -223,6 +226,15 @@ static int of_coresight_parse_endpoint(struct device *dev,
		 */
		conn->child_fwnode = fwnode_handle_get(rdev_fwnode);
		conn->child_port = rendpoint.port;
#ifdef CONFIG_CORESIGHT_QGKI
		conn->source_name = NULL;
		sn = of_parse_phandle(ep, "source", 0);
		if (sn) {
			ret = of_property_read_string(sn,
			"coresight-name", &conn->source_name);
			of_node_put(sn);
		}
#endif
		/* Connection record updated */
		ret = 1;
	} while (0);
@@ -233,7 +245,60 @@ static int of_coresight_parse_endpoint(struct device *dev,

	return ret;
}
#ifdef CONFIG_CORESIGHT_QGKI
static struct coresight_reg_clk *
of_coresight_get_reg_clk(struct device *dev, const struct device_node *node)
{
	struct coresight_reg_clk *reg_clk;
	const char *clk_name, *reg_name;
	int nr_reg, nr_clk, i, ret;

	nr_reg = of_property_count_strings(node, "qcom,proxy-regs");
	nr_clk = of_property_count_strings(node, "qcom,proxy-clks");
	if (!nr_reg && !nr_clk)
		return NULL;

	reg_clk = devm_kzalloc(dev, sizeof(*reg_clk), GFP_KERNEL);
	if (!reg_clk)
		return ERR_PTR(-ENOMEM);

	reg_clk->nr_reg = nr_reg;
	reg_clk->nr_clk = nr_clk;
	if (nr_reg > 0) {
		reg_clk->reg = devm_kzalloc(dev, nr_reg *
			sizeof(reg_clk->reg), GFP_KERNEL);
		if (!reg_clk->reg)
			return ERR_PTR(-ENOMEM);

		for (i = 0; i < nr_reg; i++) {
			ret = of_property_read_string_index(node,
				"qcom,proxy-regs", i, &reg_name);
			if (ret)
				return ERR_PTR(ret);
			reg_clk->reg[i] = devm_regulator_get(dev, reg_name);
			if (IS_ERR(reg_clk->reg[i]))
				return ERR_PTR(-EINVAL);
		}
	}
	if (nr_clk > 0) {
		reg_clk->clk = devm_kzalloc(dev, nr_clk *
			sizeof(reg_clk->clk), GFP_KERNEL);
		if (!reg_clk->clk)
			return ERR_PTR(-ENOMEM);

		for (i = 0; i < nr_clk; i++) {
			ret = of_property_read_string_index(node,
				"qcom,proxy-clks", i, &clk_name);
			if (ret)
				return ERR_PTR(ret);
			reg_clk->clk[i] = devm_clk_get(dev, clk_name);
			if (IS_ERR(reg_clk->clk[i]))
				return ERR_PTR(-EINVAL);
		}
	}
	return reg_clk;
}
#endif
static int of_get_coresight_platform_data(struct device *dev,
					  struct coresight_platform_data *pdata)
{
@@ -244,6 +309,11 @@ static int of_get_coresight_platform_data(struct device *dev,
	bool legacy_binding = false;
	struct device_node *node = dev->of_node;

#ifdef CONFIG_CORESIGHT_QGKI
	pdata->reg_clk = of_coresight_get_reg_clk(dev, node);
	if (IS_ERR(pdata->reg_clk))
		return PTR_ERR(pdata->reg_clk);
#endif
	/* Get the number of input and output port for this component */
	of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);

+138 −17
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/of_platform.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>

#include "coresight-etm-perf.h"
#include "coresight-priv.h"
@@ -54,6 +55,8 @@ static LIST_HEAD(cs_active_paths);
 */
const u32 barrier_pkt[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};

static struct coresight_device *coresight_get_source(struct list_head *path);

static int coresight_id_match(struct device *dev, void *data)
{
	int trace_id, i_trace_id;
@@ -93,6 +96,39 @@ static int coresight_source_is_unique(struct coresight_device *csdev)
				 csdev, coresight_id_match);
}

/**
 * coresight_source_filter - checks whether the connection matches the source
 * of path if connection is binded to specific source.
 * @path:	The list of devices
 * @conn:	The connection of one outport
 *
 * Return zero if the connection doesn't have a source binded or source of the
 * path matches the source binds to connection.
 */
#ifdef CONFIG_CORESIGHT_QGKI
static int coresight_source_filter(struct list_head *path,
			struct coresight_connection *conn)
{
	int ret = 0;
	struct coresight_device *source = NULL;

	if (conn->source_name == NULL)
		return ret;

	source = coresight_get_source(path);
	if (source == NULL)
		return ret;

	return strcmp(conn->source_name, dev_name(&source->dev));
}
#else
static int coresight_source_filter(struct list_head *path,
			struct coresight_connection *conn)
{
	return 0;
}
#endif

static int coresight_reset_sink(struct device *dev, void *data)
{
	struct coresight_device *csdev = to_coresight_device(dev);
@@ -110,14 +146,71 @@ static void coresight_reset_all_sink(void)
	bus_for_each_dev(&coresight_bustype, NULL, NULL, coresight_reset_sink);
}

#ifdef CONFIG_CORESIGHT_QGKI
int coresight_enable_reg_clk(struct coresight_device *csdev)
{
	struct coresight_reg_clk *reg_clk = csdev->reg_clk;
	int ret;
	int i, j;

	if (IS_ERR_OR_NULL(reg_clk))
		return -EINVAL;

	for (i = 0; i < reg_clk->nr_reg; i++) {
		ret = regulator_enable(reg_clk->reg[i]);
		if (ret)
			goto err_regs;
	}

	for (j = 0; j < reg_clk->nr_clk; j++) {
		ret = clk_prepare_enable(reg_clk->clk[j]);
		if (ret)
			goto err_clks;
	}

	return 0;
err_clks:
	for (j--; j >= 0; j--)
		clk_disable_unprepare(reg_clk->clk[j]);
err_regs:
	for (i--; i >= 0; i--)
		regulator_disable(reg_clk->reg[i]);

	return ret;
}
EXPORT_SYMBOL(coresight_enable_reg_clk);

void coresight_disable_reg_clk(struct coresight_device *csdev)
{
	struct coresight_reg_clk *reg_clk = csdev->reg_clk;
	int i;

	if (IS_ERR_OR_NULL(reg_clk))
		return;

	for (i = reg_clk->nr_clk - 1; i >= 0; i--)
		clk_disable_unprepare(reg_clk->clk[i]);
	for (i = reg_clk->nr_reg - 1; i >= 0; i--)
		regulator_disable(reg_clk->reg[i]);
}
EXPORT_SYMBOL(coresight_disable_reg_clk);
#else
int coresight_enable_reg_clk(struct coresight_device *csdev)
{ return 0; }
void coresight_disable_reg_clk(struct coresight_device *csdev) { }
#endif

static int coresight_find_link_inport(struct coresight_device *csdev,
				      struct coresight_device *parent)
				      struct coresight_device *parent,
				      struct list_head *path)
{
	int i;
	struct coresight_connection *conn;

	for (i = 0; i < parent->pdata->nr_outport; i++) {
		conn = &parent->pdata->conns[i];
		if (coresight_source_filter(path, conn))
			continue;
		if (conn->child_dev == csdev)
			return conn->child_port;
	}
@@ -129,13 +222,16 @@ static int coresight_find_link_inport(struct coresight_device *csdev,
}

static int coresight_find_link_outport(struct coresight_device *csdev,
				       struct coresight_device *child)
				       struct coresight_device *child,
				       struct list_head *path)
{
	int i;
	struct coresight_connection *conn;

	for (i = 0; i < csdev->pdata->nr_outport; i++) {
		conn = &csdev->pdata->conns[i];
		if (coresight_source_filter(path, conn))
			continue;
		if (conn->child_dev == child)
			return conn->outport;
	}
@@ -244,9 +340,12 @@ static int coresight_enable_sink(struct coresight_device *csdev,
	if (!sink_ops(csdev)->enable)
		return -EINVAL;

	coresight_enable_reg_clk(csdev);
	ret = sink_ops(csdev)->enable(csdev, mode, data);
	if (ret)
	if (ret) {
		coresight_disable_reg_clk(csdev);
		return ret;
	}
	csdev->enable = true;

	return 0;
@@ -262,13 +361,15 @@ static void coresight_disable_sink(struct coresight_device *csdev)
	ret = sink_ops(csdev)->disable(csdev);
	if (ret)
		return;
	coresight_disable_reg_clk(csdev);
	csdev->activated = false;
	csdev->enable = false;
}

static int coresight_enable_link(struct coresight_device *csdev,
				 struct coresight_device *parent,
				 struct coresight_device *child)
				 struct coresight_device *child,
				 struct list_head *path)
{
	int ret;
	int link_subtype;
@@ -277,8 +378,8 @@ static int coresight_enable_link(struct coresight_device *csdev,
	if (!parent || !child)
		return -EINVAL;

	inport = coresight_find_link_inport(csdev, parent);
	outport = coresight_find_link_outport(csdev, child);
	inport = coresight_find_link_inport(csdev, parent, path);
	outport = coresight_find_link_outport(csdev, child, path);
	link_subtype = csdev->subtype.link_subtype;

	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
@@ -293,8 +394,10 @@ static int coresight_enable_link(struct coresight_device *csdev,

	if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
		if (link_ops(csdev)->enable) {
			coresight_enable_reg_clk(csdev);
			ret = link_ops(csdev)->enable(csdev, inport, outport);
			if (ret) {
				coresight_disable_reg_clk(csdev);
				atomic_dec(&csdev->refcnt[refport]);
				return ret;
			}
@@ -308,7 +411,8 @@ static int coresight_enable_link(struct coresight_device *csdev,

static void coresight_disable_link(struct coresight_device *csdev,
				   struct coresight_device *parent,
				   struct coresight_device *child)
				   struct coresight_device *child,
				   struct list_head *path)
{
	int i, nr_conns;
	int link_subtype;
@@ -317,8 +421,8 @@ static void coresight_disable_link(struct coresight_device *csdev,
	if (!parent || !child)
		return;

	inport = coresight_find_link_inport(csdev, parent);
	outport = coresight_find_link_outport(csdev, child);
	inport = coresight_find_link_inport(csdev, parent, path);
	outport = coresight_find_link_outport(csdev, child, path);
	link_subtype = csdev->subtype.link_subtype;

	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
@@ -333,8 +437,10 @@ static void coresight_disable_link(struct coresight_device *csdev,
	}

	if (atomic_dec_return(&csdev->refcnt[refport]) == 0) {
		if (link_ops(csdev)->disable)
		if (link_ops(csdev)->disable) {
			link_ops(csdev)->disable(csdev, inport, outport);
			coresight_disable_reg_clk(csdev);
		}
	}

	for (i = 0; i < nr_conns; i++)
@@ -356,10 +462,13 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)

	if (!csdev->enable) {
		if (source_ops(csdev)->enable) {
			coresight_enable_reg_clk(csdev);
			ret = source_ops(csdev)->enable(csdev, NULL, mode);
			if (ret)
			if (ret) {
				coresight_disable_reg_clk(csdev);
				return ret;
			}
		}
		csdev->enable = true;
	}

@@ -379,8 +488,10 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
static bool coresight_disable_source(struct coresight_device *csdev)
{
	if (atomic_dec_return(csdev->refcnt) == 0) {
		if (source_ops(csdev)->disable)
		if (source_ops(csdev)->disable) {
			source_ops(csdev)->disable(csdev, NULL);
			coresight_disable_reg_clk(csdev);
		}
		csdev->enable = false;
	}
	return !csdev->enable;
@@ -430,7 +541,7 @@ static void coresight_disable_path_from(struct list_head *path,
		case CORESIGHT_DEV_TYPE_LINK:
			parent = list_prev_entry(nd, link)->csdev;
			child = list_next_entry(nd, link)->csdev;
			coresight_disable_link(csdev, parent, child);
			coresight_disable_link(csdev, parent, child, path);
			break;
		default:
			break;
@@ -484,7 +595,7 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data)
		case CORESIGHT_DEV_TYPE_LINK:
			parent = list_prev_entry(nd, link)->csdev;
			child = list_next_entry(nd, link)->csdev;
			ret = coresight_enable_link(csdev, parent, child);
			ret = coresight_enable_link(csdev, parent, child, path);
			if (ret)
				goto err;
			break;
@@ -667,7 +778,8 @@ static void coresight_drop_device(struct coresight_device *csdev)
 */
static int _coresight_build_path(struct coresight_device *csdev,
				 struct coresight_device *sink,
				 struct list_head *path)
				 struct list_head *path,
				 struct coresight_device *source)
{
	int i;
	bool found = false;
@@ -682,8 +794,14 @@ static int _coresight_build_path(struct coresight_device *csdev,
		struct coresight_device *child_dev;

		child_dev = csdev->pdata->conns[i].child_dev;
#ifdef CONFIG_CORESIGHT_QGKI
		if (csdev->pdata->conns[i].source_name &&
		    strcmp(csdev->pdata->conns[i].source_name,
				dev_name(&source->dev)))
			continue;
#endif
		if (child_dev &&
		    _coresight_build_path(child_dev, sink, path) == 0) {
		    _coresight_build_path(child_dev, sink, path, source) == 0) {
			found = true;
			break;
		}
@@ -725,7 +843,7 @@ struct list_head *coresight_build_path(struct coresight_device *source,

	INIT_LIST_HEAD(path);

	rc = _coresight_build_path(source, sink, path);
	rc = _coresight_build_path(source, sink, path, source);
	if (rc) {
		kfree(path);
		return ERR_PTR(rc);
@@ -1302,6 +1420,9 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
	csdev->subtype = desc->subtype;
	csdev->ops = desc->ops;
	csdev->orphan = false;
#ifdef CONFIG_CORESIGHT_QGKI
	csdev->reg_clk = desc->pdata->reg_clk;
#endif

	csdev->dev.type = &coresight_dev_type[desc->type];
	csdev->dev.groups = desc->groups;
Loading