devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 00/14] CoreSight CTI Driver
@ 2019-11-19 23:18 Mike Leach
  2019-11-19 23:18 ` [PATCH v5 01/14] coresight: cti: Initial " Mike Leach
                   ` (13 more replies)
  0 siblings, 14 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:18 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

CTIs are defined in the device tree and associated with other CoreSight
devices. The core CoreSight code has been modified to enable the registration
of the CTI devices on the same bus as the other CoreSight components,
but as these are not actually trace generation / capture devices, they
are not part of the Coresight path when generating trace.

However, the definition of the standard CoreSight device has been extended
to include a reference to an associated CTI device, and the enable / disable
trace path operations will auto enable/disable any associated CTI devices at
the same time.

Programming is at present via sysfs - a full API is provided to utilise the
hardware capabilities. As CTI devices are unprogrammed by default, the auto
enable describe above will have no effect until explicit programming takes
place.

A set of device tree bindings specific to the CTI topology has been defined.
The driver accesses these in a platform agnostic manner, so ACPI bindings
can be added later, once they have been agreed and defined for the CTI device.

Documentation has been updated to describe both the CTI hardware, its use and
programming in sysfs, and the new dts bindings required.

Tested on DB410 board.

Applies on coresight/next tree after following dependent set applied for
documentation directory changes [1]. Kernel version 5.4-rc7.

[1] https://www.spinics.net/lists/linux-doc/msg71062.html

Changes since v4:
Multiple changes following feedback from Mathieu, Leo and Suzuki.
1) Dropped RFC tag - wider distribution
2) CTI bindings definition now presented as a .yaml file - tested with
with 'dt-doc-validate' from devicetree.org/dt-schema project and in kernel
build tree with 'make dtbs_check' per kernel docs.
3) Sysfs links to other CoreSight devices moved out of this set into
a following set that deals with all CoreSight devices & sysfs links.
4) Documentation in .rst format and new directory following patchset in [1].
Extended example provided in docs.
5) Rationalised devicetree of_ specifics to use generic fwnode functions
where possible to enable easier addition of ACPI support later.
6) Other minor changes as requested in feedback from last patchset.

Changes since v3:
1) After discussion on CS mailing list, each CTI connection has a triggers<N>
   sysfs directory with name and trigger signals listed for the connection.
2) Initial code for creating sysfs links between CoreSight components is
  introduced and implementation for CTI provided. This allows exploration
  of the CoreSight topology within the sysfs infrastructure. Patches for
  links between other CoreSight components to follow.
3) Power management - CPU hotplug and idle omitted from this set as ongoing
   developments may define required direction. Additional patch set to follow.
4) Multiple fixes applied as requested by reviewers esp. Matthieu, Suzuki
   and Leo. 

Changes since v2:
Updates to allow for new features on coresight/next and feedback from
Mathieu and Leo.

1) Rebase and restructuring to apply on top of ACPI support patch set,
currently on coresight/next. of_coresight_cti has been renamed to
coresight-cti-platform and device tree bindings added to this but accessed
in a platform agnostic manner using fwnode for later ACPI support
to be added.
2) Split the sysfs patch info a series of functional patches.
3) Revised the refcount and enabling support.
4) Adopted the generic naming protocol - CTIs are either cti_cpuN or
cti_sysM
5) Various minor presentation /checkpatch issues highlighted in feedback.
6) revised CPU hotplug to cover missing cases needed by ETM.

Changes since v1:
1) Significant restructuring of the source code. Adds cti-sysfs file and
cti device tree file. Patches add per feature rather than per source
file.
2) CPU type power event handling for hotplug moved to CoreSight core,
with generic registration interface provided for all CPU bound CS devices
to use.
3) CTI signal interconnection details in sysfs now generated dynamically
from connection lists in driver. This to fix issue with multi-line sysfs
output in previous version.
4) Full device tree bindings for DB410 and Juno provided (to the extent
that CTI information is available).
5) AMBA driver update for UCI IDs are now upstream so no longer included
in this set.


Mike Leach (14):
  coresight: cti: Initial CoreSight CTI Driver
  coresight: cti: Add sysfs coresight mgmt reg access.
  coresight: cti: Add sysfs access to program function regs
  coresight: cti: Add sysfs trigger / channel programming API
  dt-bindings: arm: Adds CoreSight CTI hardware definitions.
  coresight: cti: Add device tree support for v8 arch CTI
  coresight: cti: Add device tree support for custom CTI.
  coresight: cti: Enable CTI associated with devices.
  coresight: cti: Add connection information to sysfs
  dt-bindings: qcom: Add CTI options for qcom msm8916
  dt-bindings: arm: Juno platform - add CTI entries to device tree.
  dt-bindings: hisilicon: Add CTI bindings for hi-6220
  docs: coresight: Update documentation for CoreSight to cover CTI.
  docs: sysfs: coresight: Add sysfs ABI documentation for CTI

 .../testing/sysfs-bus-coresight-devices-cti   |  221 +++
 .../bindings/arm/coresight-cti.yaml           |  303 ++++
 .../devicetree/bindings/arm/coresight.txt     |    7 +
 .../trace/coresight/coresight-ect.rst         |  200 +++
 Documentation/trace/coresight/coresight.rst   |   13 +
 MAINTAINERS                                   |    2 +
 arch/arm64/boot/dts/arm/juno-base.dtsi        |  150 +-
 arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi     |   31 +-
 arch/arm64/boot/dts/arm/juno-r1.dts           |   25 +
 arch/arm64/boot/dts/arm/juno-r2.dts           |   25 +
 arch/arm64/boot/dts/arm/juno.dts              |   25 +
 .../boot/dts/hisilicon/hi6220-coresight.dtsi  |  130 +-
 arch/arm64/boot/dts/qcom/msm8916.dtsi         |   85 +-
 drivers/hwtracing/coresight/Kconfig           |   12 +
 drivers/hwtracing/coresight/Makefile          |    3 +
 .../coresight/coresight-cti-platform.c        |  500 +++++++
 .../hwtracing/coresight/coresight-cti-sysfs.c | 1219 +++++++++++++++++
 drivers/hwtracing/coresight/coresight-cti.c   |  712 ++++++++++
 drivers/hwtracing/coresight/coresight-cti.h   |  232 ++++
 .../hwtracing/coresight/coresight-platform.c  |   23 +
 drivers/hwtracing/coresight/coresight-priv.h  |    7 +
 drivers/hwtracing/coresight/coresight.c       |   61 +-
 include/dt-bindings/arm/coresight-cti-dt.h    |   37 +
 include/linux/coresight.h                     |   28 +
 24 files changed, 4028 insertions(+), 23 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
 create mode 100644 Documentation/devicetree/bindings/arm/coresight-cti.yaml
 create mode 100644 Documentation/trace/coresight/coresight-ect.rst
 create mode 100644 drivers/hwtracing/coresight/coresight-cti-platform.c
 create mode 100644 drivers/hwtracing/coresight/coresight-cti-sysfs.c
 create mode 100644 drivers/hwtracing/coresight/coresight-cti.c
 create mode 100644 drivers/hwtracing/coresight/coresight-cti.h
 create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH v5 01/14] coresight: cti: Initial CoreSight CTI Driver
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
@ 2019-11-19 23:18 ` Mike Leach
  2019-11-21 20:21   ` Mathieu Poirier
  2019-11-25 19:03   ` Suzuki Kuruppassery Poulose
  2019-11-19 23:19 ` [PATCH v5 02/14] coresight: cti: Add sysfs coresight mgmt reg access Mike Leach
                   ` (12 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:18 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

This introduces a baseline CTI driver and associated configuration files.

Uses the platform agnostic naming standard for CoreSight devices, along
with a generic platform probing method that currently supports device
tree descriptions, but allows for the ACPI bindings to be added once these
have been defined for the CTI devices.

Driver will probe for the device on the AMBA bus, and load the CTI driver
on CoreSight ID match to CTI IDs in tables.

Initial sysfs support for enable / disable provided.

Default CTI interconnection data is generated based on hardware
register signal counts, with no additional connection information.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 drivers/hwtracing/coresight/Kconfig           |  12 +
 drivers/hwtracing/coresight/Makefile          |   3 +
 .../coresight/coresight-cti-platform.c        |  53 +++
 .../hwtracing/coresight/coresight-cti-sysfs.c |  72 +++
 drivers/hwtracing/coresight/coresight-cti.c   | 448 ++++++++++++++++++
 drivers/hwtracing/coresight/coresight-cti.h   | 186 ++++++++
 drivers/hwtracing/coresight/coresight.c       |   3 +
 include/linux/coresight.h                     |  23 +
 8 files changed, 800 insertions(+)
 create mode 100644 drivers/hwtracing/coresight/coresight-cti-platform.c
 create mode 100644 drivers/hwtracing/coresight/coresight-cti-sysfs.c
 create mode 100644 drivers/hwtracing/coresight/coresight-cti.c
 create mode 100644 drivers/hwtracing/coresight/coresight-cti.h

diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index 6ff30e25af55..45d3822c8c8c 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -110,4 +110,16 @@ 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 (CTI) driver"
+	depends on ARM || ARM64
+	help
+	  This driver provides support for CoreSight CTI and CTM components.
+	  These provide hardware triggering events between CoreSight trace
+	  source and sink components. These can be used to halt trace or
+	  inject events into the trace stream. CTI also provides a software
+	  control to trigger the same halt events. This can provide fast trace
+	  halt compared to disabling sources and sinks normally in driver
+	  software.
+
 endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 3c0ac421e211..0e3e72f0f510 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -17,3 +17,6 @@ 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 \
+				coresight-cti-platform.o \
+				coresight-cti-sysfs.o
diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
new file mode 100644
index 000000000000..665be86c585d
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, The Linaro Limited. All rights reserved.
+ */
+
+#include <linux/of.h>
+
+#include "coresight-cti.h"
+
+/* get the hardware configuration & connection data. */
+int cti_plat_get_hw_data(struct device *dev,
+			 struct cti_drvdata *drvdata)
+{
+	int rc = 0;
+	struct cti_device *cti_dev = &drvdata->ctidev;
+
+	/* if no connections, just add a single default based on max IN-OUT */
+	if (cti_dev->nr_trig_con == 0)
+		rc = cti_add_default_connection(dev, drvdata);
+	return rc;
+}
+
+struct coresight_platform_data *
+coresight_cti_get_platform_data(struct device *dev)
+{
+	int ret = -ENOENT;
+	struct coresight_platform_data *pdata = NULL;
+	struct fwnode_handle *fwnode = dev_fwnode(dev);
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev);
+
+	if (IS_ERR_OR_NULL(fwnode))
+		goto error;
+
+	/*
+	 * Alloc platform data but leave it zero init. CTI does not use the
+	 * same connection infrastructuree as trace path components but an
+	 * empty struct enables us to use the standard coresight component
+	 * registration code.
+	 */
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	/* get some CTI specifics */
+	ret = cti_plat_get_hw_data(dev, drvdata);
+
+	if (!ret)
+		return pdata;
+error:
+	return ERR_PTR(ret);
+}
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
new file mode 100644
index 000000000000..a832b8c6b866
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Linaro Limited, All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#include <linux/coresight.h>
+
+#include "coresight-cti.h"
+
+/* basic attributes */
+static ssize_t enable_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	int enable_req;
+	bool enabled, powered;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	ssize_t size = 0;
+
+	enable_req = atomic_read(&drvdata->config.enable_req_count);
+	spin_lock(&drvdata->spinlock);
+	powered = drvdata->config.hw_powered;
+	enabled = drvdata->config.hw_enabled;
+	spin_unlock(&drvdata->spinlock);
+
+	if (powered) {
+		size = scnprintf(buf, PAGE_SIZE, "cti %s; powered;\n",
+				 enabled ? "enabled" : "disabled");
+	} else {
+		size = scnprintf(buf, PAGE_SIZE, "cti %s; unpowered;\n",
+				 enable_req ? "enable req" : "disabled");
+	}
+	return size;
+}
+
+static ssize_t enable_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t size)
+{
+	int ret = 0;
+	unsigned long val;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return ret;
+
+	if (val)
+		ret = cti_enable(drvdata->csdev);
+	else
+		ret = cti_disable(drvdata->csdev);
+	if (ret)
+		return ret;
+	return size;
+}
+static DEVICE_ATTR_RW(enable);
+
+/* attribute and group sysfs tables. */
+static struct attribute *coresight_cti_attrs[] = {
+	&dev_attr_enable.attr,
+	NULL,
+};
+
+static const struct attribute_group coresight_cti_group = {
+	.attrs = coresight_cti_attrs,
+};
+
+const struct attribute_group *coresight_cti_groups[] = {
+	&coresight_cti_group,
+	NULL,
+};
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
new file mode 100644
index 000000000000..7ae48bf62d17
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cti.c
@@ -0,0 +1,448 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Linaro Limited, All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#include "coresight-cti.h"
+
+/**
+ * CTI devices can be associated with a PE, or be connected to CoreSight
+ * hardware. We have a list of all CTIs irrespective of CPU bound or
+ * otherwise.
+ *
+ * We assume that the non-CPU CTIs are always powered as we do with sinks etc.
+ *
+ * We leave the client to figure out if all the CTIs are interconnected with
+ * the same CTM, in general this is the case but does not always have to be.
+ */
+
+/* net of CTI devices connected via CTM */
+LIST_HEAD(ect_net);
+
+/* protect the list */
+static DEFINE_MUTEX(ect_mutex);
+
+#define csdev_to_cti_drvdata(csdev)	\
+	dev_get_drvdata(csdev->dev.parent)
+
+/*
+ * CTI naming. CTI bound to cores will have the name cti_cpu<N> where
+ * N is the CPU ID. System CTIs will have the name cti_sys<I> where I
+ * is an index allocated by order of discovery.
+ *
+ * CTI device name list - for CTI not bound to cores.
+ */
+DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys");
+
+/* write set of regs to hardware - call with spinlock claimed */
+void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
+{
+	struct cti_config *config = &drvdata->config;
+	int i;
+
+	CS_UNLOCK(drvdata->base);
+
+	/* disable CTI before writing registers */
+	writel_relaxed(0, drvdata->base + CTICONTROL);
+
+	/* write the CTI trigger registers */
+	for (i = 0; i < config->nr_trig_max; i++) {
+		writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i));
+		writel_relaxed(config->ctiouten[i],
+			       drvdata->base + CTIOUTEN(i));
+	}
+
+	/* other regs */
+	writel_relaxed(config->ctigate, drvdata->base + CTIGATE);
+	writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
+	writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);
+
+	/* re-enable CTI */
+	writel_relaxed(1, drvdata->base + CTICONTROL);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void cti_enable_hw_smp_call(void *info)
+{
+	struct cti_drvdata *drvdata = info;
+
+	cti_write_all_hw_regs(drvdata);
+}
+
+/* write regs to hardware and enable */
+static int cti_enable_hw(struct cti_drvdata *drvdata)
+{
+	struct cti_config *config = &drvdata->config;
+	struct device *dev = &drvdata->csdev->dev;
+	int rc = 0;
+
+	pm_runtime_get_sync(dev->parent);
+	spin_lock(&drvdata->spinlock);
+
+	/* no need to do anything if enabled or unpowered*/
+	if (config->hw_enabled || !config->hw_powered)
+		goto cti_state_unchanged;
+
+	/* claim the device */
+	rc = coresight_claim_device(drvdata->base);
+	if (rc)
+		goto cti_err_not_enabled;
+
+	if (drvdata->ctidev.cpu >= 0) {
+		rc = smp_call_function_single(drvdata->ctidev.cpu,
+					      cti_enable_hw_smp_call,
+					      drvdata, 1);
+		if (rc)
+			goto cti_err_not_enabled;
+	} else {
+		cti_write_all_hw_regs(drvdata);
+	}
+
+	config->hw_enabled = true;
+	atomic_inc(&drvdata->config.enable_req_count);
+	spin_unlock(&drvdata->spinlock);
+	return rc;
+
+cti_state_unchanged:
+	atomic_inc(&drvdata->config.enable_req_count);
+
+	/* cannot enable due to error */
+cti_err_not_enabled:
+	spin_unlock(&drvdata->spinlock);
+	pm_runtime_put(dev->parent);
+	return rc;
+}
+
+/* disable hardware */
+static int cti_disable_hw(struct cti_drvdata *drvdata)
+{
+	struct cti_config *config = &drvdata->config;
+	struct device *dev = &drvdata->csdev->dev;
+
+	spin_lock(&drvdata->spinlock);
+
+	/* check refcount - disable on 0 */
+	if (atomic_dec_return(&drvdata->config.enable_req_count) > 0)
+		goto cti_not_disabled;
+
+	/* no need to do anything if disabled or cpu unpowered */
+	if (!config->hw_enabled || !config->hw_powered)
+		goto cti_not_disabled;
+
+	CS_UNLOCK(drvdata->base);
+
+	/* disable CTI */
+	writel_relaxed(0, drvdata->base + CTICONTROL);
+	config->hw_enabled = false;
+
+	coresight_disclaim_device_unlocked(drvdata->base);
+	CS_LOCK(drvdata->base);
+	spin_unlock(&drvdata->spinlock);
+	pm_runtime_put(dev);
+	return 0;
+
+	/* not disabled this call */
+cti_not_disabled:
+	spin_unlock(&drvdata->spinlock);
+	return 0;
+}
+
+/*
+ * Look at the HW DEVID register for some of the HW settings.
+ * DEVID[15:8] - max number of in / out triggers.
+ */
+#define CTI_DEVID_MAXTRIGS(devid_val) (int)((devid_val & 0xFF00) >> 8)
+
+/* DEVID[19:16] - number of CTM channels */
+#define CTI_DEVID_CTMCHANNELS(devid_val) (int)((devid_val & 0xF0000) >> 16)
+
+static void cti_set_default_config(struct device *dev,
+				   struct cti_drvdata *drvdata)
+{
+	struct cti_config *config = &drvdata->config;
+	u32 devid;
+
+	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
+	config->nr_trig_max = CTI_DEVID_MAXTRIGS(devid);
+
+	/*
+	 * no current hardware should exceed this, but protect the driver
+	 * in case of fault / out of spec hw
+	 */
+	if (config->nr_trig_max > CTIINOUTEN_MAX) {
+		dev_warn_once(dev,
+			"Limiting HW MaxTrig value(%d) to driver max(%d)\n",
+			config->nr_trig_max, CTIINOUTEN_MAX);
+		config->nr_trig_max = CTIINOUTEN_MAX;
+	}
+
+	config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid);
+
+	/* Most regs default to 0 as zalloc'ed except...*/
+	config->trig_filter_enable = true;
+	config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
+	atomic_set(&config->enable_req_count, 0);
+}
+
+/*
+ * Add a connection entry to the list of connections for this
+ * CTI device.
+ */
+int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
+			     struct cti_trig_con *tc,
+			     struct coresight_device *csdev,
+			     const char *assoc_dev_name)
+{
+	struct cti_device *cti_dev = &drvdata->ctidev;
+
+	tc->con_dev = csdev;
+	/*
+	 * Prefer actual associated CS device dev name to supplied value -
+	 * which is likely to be node name / other conn name.
+	 */
+	if (csdev)
+		tc->con_dev_name = devm_kstrdup(dev,
+						dev_name(&csdev->dev),
+						GFP_KERNEL);
+	else if (assoc_dev_name != NULL)
+		tc->con_dev_name = devm_kstrdup(dev,
+						assoc_dev_name, GFP_KERNEL);
+	list_add_tail(&tc->node, &cti_dev->trig_cons);
+	cti_dev->nr_trig_con++;
+
+	/* add connection usage bit info to overall info */
+	drvdata->config.trig_in_use |= tc->con_in->used_mask;
+	drvdata->config.trig_out_use |= tc->con_out->used_mask;
+
+	return 0;
+}
+
+/* create a trigger connection with appropriately sized signal groups */
+struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
+					   int out_sigs)
+{
+	struct cti_trig_con *tc = NULL;
+	struct cti_trig_grp *in = NULL, *out = NULL;
+
+	tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL);
+	if (!tc)
+		return tc;
+
+	in = devm_kzalloc(dev,
+			  offsetof(struct cti_trig_grp, sig_types[in_sigs]),
+			  GFP_KERNEL);
+	if (!in)
+		return NULL;
+
+	out = devm_kzalloc(dev,
+			   offsetof(struct cti_trig_grp, sig_types[out_sigs]),
+			   GFP_KERNEL);
+	if (!out)
+		return NULL;
+
+	tc->con_in = in;
+	tc->con_out = out;
+	tc->con_in->nr_sigs = in_sigs;
+	tc->con_out->nr_sigs = out_sigs;
+	return tc;
+}
+
+/*
+ * Add a default connection if nothing else is specified.
+ * single connection based on max in/out info, no assoc device
+ */
+int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
+{
+	int ret = 0;
+	int n_trigs = drvdata->config.nr_trig_max;
+	u32 n_trig_mask = GENMASK(n_trigs - 1, 0);
+	struct cti_trig_con *tc = NULL;
+
+	/*
+	 * Assume max trigs for in and out,
+	 * all used, default sig types allocated
+	 */
+	tc = cti_allocate_trig_con(dev, n_trigs, n_trigs);
+	if (!tc)
+		return -ENOMEM;
+
+	tc->con_in->used_mask = n_trig_mask;
+	tc->con_out->used_mask = n_trig_mask;
+	ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default");
+	return ret;
+}
+
+/** cti ect operations **/
+int cti_enable(struct coresight_device *csdev)
+{
+	struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
+
+	/* enable hardware with refcount */
+	return cti_enable_hw(drvdata);
+}
+
+int cti_disable(struct coresight_device *csdev)
+{
+	struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
+
+	/* disable hardware with refcount */
+	return cti_disable_hw(drvdata);
+}
+
+const struct coresight_ops_ect cti_ops_ect = {
+	.enable = cti_enable,
+	.disable = cti_disable,
+};
+
+const struct coresight_ops cti_ops = {
+	.ect_ops = &cti_ops_ect,
+};
+
+/*
+ * Free up CTI specific resources
+ * called by dev->release, need to call down to underlying csdev release.
+ */
+static void cti_device_release(struct device *dev)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_drvdata *ect_item, *ect_tmp;
+
+	mutex_lock(&ect_mutex);
+
+	/* remove from the list */
+	list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
+		if (ect_item == drvdata) {
+			list_del(&ect_item->node);
+			break;
+		}
+	}
+	mutex_unlock(&ect_mutex);
+
+	if (drvdata->csdev_release)
+		drvdata->csdev_release(dev);
+}
+
+static int cti_probe(struct amba_device *adev, const struct amba_id *id)
+{
+	int ret = 0;
+	void __iomem *base;
+	struct device *dev = &adev->dev;
+	struct cti_drvdata *drvdata = NULL;
+	struct coresight_desc cti_desc;
+	struct coresight_platform_data *pdata = NULL;
+	struct resource *res = &adev->res;
+
+	/* driver data*/
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata) {
+		ret = -ENOMEM;
+		dev_info(dev, "%s, mem err\n", __func__);
+		goto err_out;
+	}
+
+	/* Validity for the resource is already checked by the AMBA core */
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
+		dev_info(dev, "%s, remap err\n", __func__);
+		goto err_out;
+	}
+	drvdata->base = base;
+
+	dev_set_drvdata(dev, drvdata);
+
+	/* default CTI device info  */
+	drvdata->ctidev.cpu = -1;
+	drvdata->ctidev.nr_trig_con = 0;
+	drvdata->ctidev.ctm_id = 0;
+	INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);
+
+	spin_lock_init(&drvdata->spinlock);
+
+	/* initialise CTI driver config values */
+	cti_set_default_config(dev, drvdata);
+
+	/* Parse the .dts for connections and signals */
+	pdata = coresight_cti_get_platform_data(dev);
+	if (IS_ERR(pdata)) {
+		dev_info(dev, "coresight_cti_get_platform_data err\n");
+		ret =  PTR_ERR(pdata);
+		goto err_out;
+	}
+
+	/* default to powered - could change on PM notifications */
+	drvdata->config.hw_powered = true;
+
+	/* set up device name - will depend if cpu bound or otherwise */
+	if (drvdata->ctidev.cpu >= 0)
+		cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d",
+					       drvdata->ctidev.cpu);
+	else
+		cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev);
+	if (!cti_desc.name) {
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	/* set up coresight component description */
+	cti_desc.pdata = pdata;
+	cti_desc.type = CORESIGHT_DEV_TYPE_ECT;
+	cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI;
+	cti_desc.ops = &cti_ops;
+	cti_desc.groups = coresight_cti_groups;
+	cti_desc.dev = dev;
+	drvdata->csdev = coresight_register(&cti_desc);
+	if (IS_ERR(drvdata->csdev)) {
+		ret = PTR_ERR(drvdata->csdev);
+		goto err_out;
+	}
+
+	/* add to list of CTI devices */
+	mutex_lock(&ect_mutex);
+	list_add(&drvdata->node, &ect_net);
+	mutex_unlock(&ect_mutex);
+
+	/* set up release chain */
+	drvdata->csdev_release = drvdata->csdev->dev.release;
+	drvdata->csdev->dev.release = cti_device_release;
+
+	/* all done - dec pm refcount */
+	pm_runtime_put(&adev->dev);
+	dev_info(&drvdata->csdev->dev, "CTI initialized\n");
+	return 0;
+
+err_out:
+	return ret;
+}
+
+static struct amba_cs_uci_id uci_id_cti[] = {
+	{
+		/*  CTI UCI data */
+		.devarch	= 0x47701a14, /* CTI v2 */
+		.devarch_mask	= 0xfff0ffff,
+		.devtype	= 0x00000014, /* maj(0x4-debug) min(0x1-ECT) */
+	}
+};
+
+static const struct amba_id cti_ids[] = {
+	CS_AMBA_ID(0x000bb906), /* Coresight CTI (SoC 400), C-A72, C-A57 */
+	CS_AMBA_ID(0x000bb922), /* CTI - C-A8 */
+	CS_AMBA_ID(0x000bb9a8), /* CTI - C-A53 */
+	CS_AMBA_ID(0x000bb9aa), /* CTI - C-A73 */
+	CS_AMBA_UCI_ID(0x000bb9da, uci_id_cti), /* CTI - C-A35 */
+	CS_AMBA_UCI_ID(0x000bb9ed, uci_id_cti), /* Coresight CTI (SoC 600) */
+	{ 0, 0},
+};
+
+static struct amba_driver cti_driver = {
+	.drv = {
+		.name	= "coresight-cti",
+		.owner = THIS_MODULE,
+		.suppress_bind_attrs = true,
+	},
+	.probe		= cti_probe,
+	.id_table	= cti_ids,
+};
+builtin_amba_driver(cti_driver);
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
new file mode 100644
index 000000000000..e0d476533a82
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 Linaro Limited, All rights reserved.
+ * Author: Mike Leach <mike.leach@linaro.org>
+ */
+
+#ifndef _CORESIGHT_CORESIGHT_CTI_H
+#define _CORESIGHT_CORESIGHT_CTI_H
+
+#include <asm/local.h>
+#include <linux/spinlock.h>
+#include "coresight-priv.h"
+
+/*
+ * Device registers
+ * 0x000 - 0x144: CTI programming and status
+ * 0xEDC - 0xEF8: CTI integration test.
+ * 0xF00 - 0xFFC: Coresight management registers.
+ */
+/* CTI programming registers */
+#define CTICONTROL		0x000
+#define CTIINTACK		0x010
+#define CTIAPPSET		0x014
+#define CTIAPPCLEAR		0x018
+#define CTIAPPPULSE		0x01C
+#define CTIINEN(n)		(0x020 + (4 * n))
+#define CTIOUTEN(n)		(0x0A0 + (4 * n))
+#define CTITRIGINSTATUS		0x130
+#define CTITRIGOUTSTATUS	0x134
+#define CTICHINSTATUS		0x138
+#define CTICHOUTSTATUS		0x13C
+#define CTIGATE			0x140
+#define ASICCTL			0x144
+/* Integration test registers */
+#define ITCHINACK		0xEDC /* WO CTI CSSoc 400 only*/
+#define ITTRIGINACK		0xEE0 /* WO CTI CSSoc 400 only*/
+#define ITCHOUT			0xEE4 /* WO RW-600 */
+#define ITTRIGOUT		0xEE8 /* WO RW-600 */
+#define ITCHOUTACK		0xEEC /* RO CTI CSSoc 400 only*/
+#define ITTRIGOUTACK		0xEF0 /* RO CTI CSSoc 400 only*/
+#define ITCHIN			0xEF4 /* RO */
+#define ITTRIGIN		0xEF8 /* RO */
+/* management registers */
+#define CTIDEVAFF0		0xFA8
+#define CTIDEVAFF1		0xFAC
+
+/*
+ * CTI CSSoc 600 has a max of 32 trigger signals per direction.
+ * CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def.
+ * Max of in and out defined in the DEVID register.
+ * - pick up actual number used from .dts parameters if present.
+ */
+#define CTIINOUTEN_MAX		32
+
+/**
+ * Group of related trigger signals
+ *
+ * @nr_sigs: number of signals in the group.
+ * @used_mask: bitmask representing the signal indexes in the group.
+ * @sig_types: array of types for the signals, length nr_sigs.
+ */
+struct cti_trig_grp {
+	int nr_sigs;
+	u32 used_mask;
+	int sig_types[0];
+};
+
+/**
+ * Trigger connection - connection between a CTI and other (coresight) device
+ * lists input and output trigger signals for the device
+ *
+ * @con_in: connected CTIIN signals for the device.
+ * @con_out: connected CTIOUT signals for the device.
+ * @con_dev: coresight device connected to the CTI, NULL if not CS device
+ * @con_dev_name: name of connected device (CS or CPU)
+ * @node: entry node in list of connections.
+ */
+struct cti_trig_con {
+	struct cti_trig_grp *con_in;
+	struct cti_trig_grp *con_out;
+	struct coresight_device *con_dev;
+	char *con_dev_name;
+	struct list_head node;
+};
+
+/**
+ * struct cti_device - description of CTI device properties.
+ *
+ * @nt_trig_con: Number of external devices connected to this device.
+ * @ctm_id: which CTM this device is connected to (by default it is
+ *          assumed there is a single CTM per SoC, ID 0).
+ * @trig_cons: list of connections to this device.
+ * @cpu: CPU ID if associated with CPU, -1 otherwise.
+ */
+struct cti_device {
+	int nr_trig_con;
+	u32 ctm_id;
+	struct list_head trig_cons;
+	int cpu;
+};
+
+/**
+ * struct cti_config - configuration of the CTI device hardware
+ *
+ * @nr_trig_max: Max number of trigger signals implemented on device.
+ *		 (max of trig_in or trig_out) - from ID register.
+ * @nr_ctm_channels: number of available CTM channels - from ID register.
+ * @enable_req_count: CTI is enabled alongside >=1 associated devices.
+ * @hw_enabled: true if hw is currently enabled.
+ * @hw_powered: true if associated cpu powered on, or no cpu.
+ * @trig_in_use: bitfield of in triggers registered as in use.
+ * @trig_out_use: bitfield of out triggers registered as in use.
+ * @trig_out_filter: bitfield of out triggers that are blocked if filter
+ *	             enabled. Typically this would be dbgreq / restart on
+ *		     a core CTI.
+ * @trig_filter_enable: 1 if filtering enabled.
+ * @xtrig_rchan_sel: channel selection for xtrigger connection show.
+ * @ctiappset: CTI Software application channel set.
+ * @ctiinout_sel: register selector for INEN and OUTEN regs.
+ * @ctiinen: enable input trigger to a channel.
+ * @ctiouten: enable output trigger from a channel.
+ * @ctigate: gate channel output from CTI to CTM.
+ * @asicctl: asic control register.
+ */
+struct cti_config {
+	/* hardware description */
+	int nr_ctm_channels;
+	int nr_trig_max;
+
+	/* cti enable control */
+	atomic_t enable_req_count;
+	bool hw_enabled;
+	bool hw_powered;
+
+	/* registered triggers and filtering */
+	u32 trig_in_use;
+	u32 trig_out_use;
+	u32 trig_out_filter;
+	bool trig_filter_enable;
+	u8 xtrig_rchan_sel;
+
+	/* cti cross trig programmable regs */
+	u32 ctiappset;
+	u8 ctiinout_sel;
+	u32 ctiinen[CTIINOUTEN_MAX];
+	u32 ctiouten[CTIINOUTEN_MAX];
+	u32 ctigate;
+	u32 asicctl;
+};
+
+/**
+ * struct cti_drvdata - specifics for the CTI device
+ * @base:	Memory mapped base address for this component..
+ * @csdev:	Standard CoreSight device information.
+ * @ctidev:	Extra information needed by the CTI/CTM framework.
+ * @spinlock:	Control data access to one at a time.
+ * @config:	Configuration data for this CTI device.
+ * @node:	List entry of this device in the list of CTI devices.
+ * @csdev_release: release function for underlying coresight_device.
+ */
+struct cti_drvdata {
+	void __iomem *base;
+	struct coresight_device	*csdev;
+	struct cti_device ctidev;
+	spinlock_t spinlock;
+	struct cti_config config;
+	struct list_head node;
+	void (*csdev_release)(struct device *dev);
+};
+
+/* private cti driver fns & vars */
+extern const struct attribute_group *coresight_cti_groups[];
+int cti_add_default_connection(struct device *dev,
+			       struct cti_drvdata *drvdata);
+int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
+			     struct cti_trig_con *tc,
+			     struct coresight_device *csdev,
+			     const char *assoc_dev_name);
+struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
+					   int out_sigs);
+int cti_enable(struct coresight_device *csdev);
+int cti_disable(struct coresight_device *csdev);
+struct coresight_platform_data *
+coresight_cti_get_platform_data(struct device *dev);
+
+#endif  /* _CORESIGHT_CORESIGHT_CTI_H */
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index ef20f74c85fa..1a5fdf2710ff 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -955,6 +955,9 @@ static struct device_type coresight_dev_type[] = {
 	{
 		.name = "helper",
 	},
+	{
+		.name = "ect",
+	},
 };
 
 static void coresight_device_release(struct device *dev)
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 44e552de419c..b3e582d96a34 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -41,6 +41,7 @@ enum coresight_dev_type {
 	CORESIGHT_DEV_TYPE_LINKSINK,
 	CORESIGHT_DEV_TYPE_SOURCE,
 	CORESIGHT_DEV_TYPE_HELPER,
+	CORESIGHT_DEV_TYPE_ECT,
 };
 
 enum coresight_dev_subtype_sink {
@@ -68,6 +69,12 @@ enum coresight_dev_subtype_helper {
 	CORESIGHT_DEV_SUBTYPE_HELPER_CATU,
 };
 
+/* Embedded Cross Trigger (ECT) sub-types */
+enum coresight_dev_subtype_ect {
+	CORESIGHT_DEV_SUBTYPE_ECT_NONE,
+	CORESIGHT_DEV_SUBTYPE_ECT_CTI,
+};
+
 /**
  * union coresight_dev_subtype - further characterisation of a type
  * @sink_subtype:	type of sink this component is, as defined
@@ -78,6 +85,8 @@ enum coresight_dev_subtype_helper {
  *			by @coresight_dev_subtype_source.
  * @helper_subtype:	type of helper this component is, as defined
  *			by @coresight_dev_subtype_helper.
+ * @ect_subtype:        type of cross trigger this component is, as
+ *			defined by @coresight_dev_subtype_ect
  */
 union coresight_dev_subtype {
 	/* We have some devices which acts as LINK and SINK */
@@ -87,6 +96,7 @@ union coresight_dev_subtype {
 	};
 	enum coresight_dev_subtype_source source_subtype;
 	enum coresight_dev_subtype_helper helper_subtype;
+	enum coresight_dev_subtype_ect ect_subtype;
 };
 
 /**
@@ -196,6 +206,7 @@ static struct coresight_dev_list (var) = {				\
 #define sink_ops(csdev)		csdev->ops->sink_ops
 #define link_ops(csdev)		csdev->ops->link_ops
 #define helper_ops(csdev)	csdev->ops->helper_ops
+#define ect_ops(csdev)		csdev->ops->ect_ops
 
 /**
  * struct coresight_ops_sink - basic operations for a sink
@@ -262,11 +273,23 @@ struct coresight_ops_helper {
 	int (*disable)(struct coresight_device *csdev, void *data);
 };
 
+/**
+ * struct coresight_ops_ect - Ops for an embedded cross trigger device
+ *
+ * @enable	: Enable the device
+ * @disable	: Disable the device
+ */
+struct coresight_ops_ect {
+	int (*enable)(struct coresight_device *csdev);
+	int (*disable)(struct coresight_device *csdev);
+};
+
 struct coresight_ops {
 	const struct coresight_ops_sink *sink_ops;
 	const struct coresight_ops_link *link_ops;
 	const struct coresight_ops_source *source_ops;
 	const struct coresight_ops_helper *helper_ops;
+	const struct coresight_ops_ect *ect_ops;
 };
 
 #ifdef CONFIG_CORESIGHT
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 02/14] coresight: cti: Add sysfs coresight mgmt reg access.
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
  2019-11-19 23:18 ` [PATCH v5 01/14] coresight: cti: Initial " Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-22 17:19   ` Mathieu Poirier
  2019-11-19 23:19 ` [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs Mike Leach
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Adds sysfs access to the coresight management registers.

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../hwtracing/coresight/coresight-cti-sysfs.c | 53 +++++++++++++++++++
 drivers/hwtracing/coresight/coresight-priv.h  |  1 +
 2 files changed, 54 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index a832b8c6b866..507f8eb487fe 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -62,11 +62,64 @@ static struct attribute *coresight_cti_attrs[] = {
 	NULL,
 };
 
+/* register based attributes */
+
+/* macro to access RO registers with power check only (no enable check). */
+#define coresight_cti_reg(name, offset)			\
+static ssize_t name##_show(struct device *dev,				\
+			   struct device_attribute *attr, char *buf)	\
+{									\
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);	\
+	u32 val = 0;							\
+	pm_runtime_get_sync(dev->parent);				\
+	spin_lock(&drvdata->spinlock);					\
+	if (drvdata->config.hw_powered)					\
+		val = readl_relaxed(drvdata->base + offset);		\
+	spin_unlock(&drvdata->spinlock);				\
+	pm_runtime_put_sync(dev->parent);				\
+	return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);		\
+}									\
+static DEVICE_ATTR_RO(name)
+
+/* coresight management registers */
+coresight_cti_reg(devaff0, CTIDEVAFF0);
+coresight_cti_reg(devaff1, CTIDEVAFF1);
+coresight_cti_reg(authstatus, CORESIGHT_AUTHSTATUS);
+coresight_cti_reg(devarch, CORESIGHT_DEVARCH);
+coresight_cti_reg(devid, CORESIGHT_DEVID);
+coresight_cti_reg(devtype, CORESIGHT_DEVTYPE);
+coresight_cti_reg(pidr0, CORESIGHT_PERIPHIDR0);
+coresight_cti_reg(pidr1, CORESIGHT_PERIPHIDR1);
+coresight_cti_reg(pidr2, CORESIGHT_PERIPHIDR2);
+coresight_cti_reg(pidr3, CORESIGHT_PERIPHIDR3);
+coresight_cti_reg(pidr4, CORESIGHT_PERIPHIDR4);
+
+static struct attribute *coresight_cti_mgmt_attrs[] = {
+	&dev_attr_devaff0.attr,
+	&dev_attr_devaff1.attr,
+	&dev_attr_authstatus.attr,
+	&dev_attr_devarch.attr,
+	&dev_attr_devid.attr,
+	&dev_attr_devtype.attr,
+	&dev_attr_pidr0.attr,
+	&dev_attr_pidr1.attr,
+	&dev_attr_pidr2.attr,
+	&dev_attr_pidr3.attr,
+	&dev_attr_pidr4.attr,
+	NULL,
+};
+
 static const struct attribute_group coresight_cti_group = {
 	.attrs = coresight_cti_attrs,
 };
 
+static const struct attribute_group coresight_cti_mgmt_group = {
+	.attrs = coresight_cti_mgmt_attrs,
+	.name = "mgmt",
+};
+
 const struct attribute_group *coresight_cti_groups[] = {
 	&coresight_cti_group,
+	&coresight_cti_mgmt_group,
 	NULL,
 };
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 82e563cdc879..aba6b789c969 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -22,6 +22,7 @@
 #define CORESIGHT_CLAIMCLR	0xfa4
 #define CORESIGHT_LAR		0xfb0
 #define CORESIGHT_LSR		0xfb4
+#define CORESIGHT_DEVARCH	0xfbc
 #define CORESIGHT_AUTHSTATUS	0xfb8
 #define CORESIGHT_DEVID		0xfc8
 #define CORESIGHT_DEVTYPE	0xfcc
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
  2019-11-19 23:18 ` [PATCH v5 01/14] coresight: cti: Initial " Mike Leach
  2019-11-19 23:19 ` [PATCH v5 02/14] coresight: cti: Add sysfs coresight mgmt reg access Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-27 18:26   ` Suzuki Kuruppassery Poulose
  2019-11-28 10:54   ` Suzuki Kuruppassery Poulose
  2019-11-19 23:19 ` [PATCH v5 04/14] coresight: cti: Add sysfs trigger / channel programming API Mike Leach
                   ` (10 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Adds in sysfs programming support for the CTI function register sets.
Allows direct manipulation of channel / trigger association registers.

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../hwtracing/coresight/coresight-cti-sysfs.c | 362 ++++++++++++++++++
 drivers/hwtracing/coresight/coresight-cti.c   |  19 +
 drivers/hwtracing/coresight/coresight-cti.h   |   5 +
 3 files changed, 386 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 507f8eb487fe..02d3ee0c1278 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -109,6 +109,362 @@ static struct attribute *coresight_cti_mgmt_attrs[] = {
 	NULL,
 };
 
+/* CTI low level programming registers */
+
+/*
+ * Show a simple 32 bit value if enabled and powered.
+ * If inaccessible & pcached_val not NULL then show cached value.
+ */
+static ssize_t cti_reg32_show(struct device *dev, char *buf,
+			      u32 *pcached_val, int reg_offset)
+{
+	u32 val = 0;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	if ((reg_offset >= 0) && CTI_PWR_ENA(config)) {
+		CS_UNLOCK(drvdata->base);
+		val = readl_relaxed(drvdata->base + reg_offset);
+		if (pcached_val)
+			*pcached_val = val;
+		CS_LOCK(drvdata->base);
+	} else if (pcached_val) {
+		val = *pcached_val;
+	}
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#x\n", val);
+}
+
+/*
+ * Store a simple 32 bit value.
+ * If pcached_val not NULL, then copy to here too,
+ * if reg_offset >= 0 then write through if enabled.
+ */
+static ssize_t cti_reg32_store(struct device *dev, const char *buf,
+			       size_t size, u32 *pcached_val, int reg_offset)
+{
+	unsigned long val;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	/* local store */
+	if (pcached_val)
+		*pcached_val = (u32)val;
+
+	/* write through if offset and enabled */
+	if ((reg_offset >= 0) && CTI_PWR_ENA(config))
+		cti_write_single_reg(drvdata, reg_offset, val);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+
+/* Standard macro for simple rw cti config registers */
+#define cti_config_reg32_rw(name, cfgname, offset)			\
+static ssize_t name##_show(struct device *dev,				\
+			   struct device_attribute *attr,		\
+			   char *buf)					\
+{									\
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);	\
+	return cti_reg32_show(dev, buf,					\
+			      &drvdata->config.cfgname, offset);	\
+}									\
+									\
+static ssize_t name##_store(struct device *dev,				\
+			    struct device_attribute *attr,		\
+			    const char *buf, size_t size)		\
+{									\
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);	\
+	return cti_reg32_store(dev, buf, size,				\
+			       &drvdata->config.cfgname, offset);	\
+}									\
+static DEVICE_ATTR_RW(name)
+
+static ssize_t inout_sel_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	u32 val;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = (u32)drvdata->config.ctiinout_sel;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t inout_sel_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	unsigned long val;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+	if (val > (CTIINOUTEN_MAX - 1))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	drvdata->config.ctiinout_sel = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(inout_sel);
+
+static ssize_t inen_show(struct device *dev,
+			 struct device_attribute *attr,
+			 char *buf)
+{
+	unsigned long val;
+	int index;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	spin_lock(&drvdata->spinlock);
+	index = drvdata->config.ctiinout_sel;
+	val = drvdata->config.ctiinen[index];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "INEN%d %#lx\n", index, val);
+}
+
+static ssize_t inen_store(struct device *dev,
+			  struct device_attribute *attr,
+			  const char *buf, size_t size)
+{
+	unsigned long val;
+	int index;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	index = config->ctiinout_sel;
+	config->ctiinen[index] = val;
+
+	/* write through if enabled */
+	if (CTI_PWR_ENA(config))
+		cti_write_single_reg(drvdata, CTIINEN(index), val);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(inen);
+
+static ssize_t outen_show(struct device *dev,
+			  struct device_attribute *attr,
+			  char *buf)
+{
+	unsigned long val;
+	int index;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	spin_lock(&drvdata->spinlock);
+	index = drvdata->config.ctiinout_sel;
+	val = drvdata->config.ctiouten[index];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "OUTEN%d %#lx\n", index, val);
+}
+
+static ssize_t outen_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t size)
+{
+	unsigned long val;
+	int index;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	index = config->ctiinout_sel;
+	config->ctiouten[index] = val;
+
+	/* write through if enabled */
+	if (CTI_PWR_ENA(config))
+		cti_write_single_reg(drvdata, CTIOUTEN(index), val);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(outen);
+
+static ssize_t intack_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t size)
+{
+	unsigned long val;
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	cti_write_intack(dev, val);
+	return size;
+}
+static DEVICE_ATTR_WO(intack);
+
+cti_config_reg32_rw(gate, ctigate, CTIGATE);
+cti_config_reg32_rw(asicctl, asicctl, ASICCTL);
+cti_config_reg32_rw(appset, ctiappset, CTIAPPSET);
+
+static ssize_t appclear_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+
+	/* a 1'b1 in appclr clears down the same bit in appset*/
+	config->ctiappset &= ~val;
+
+	/* write through if enabled */
+	if (CTI_PWR_ENA(config))
+		cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_WO(appclear);
+
+static ssize_t apppulse_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+
+	/* write through if enabled */
+	if (CTI_PWR_ENA(config))
+		cti_write_single_reg(drvdata, CTIAPPPULSE, val);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_WO(apppulse);
+
+coresight_cti_reg(triginstatus, CTITRIGINSTATUS);
+coresight_cti_reg(trigoutstatus, CTITRIGOUTSTATUS);
+coresight_cti_reg(chinstatus, CTICHINSTATUS);
+coresight_cti_reg(choutstatus, CTICHOUTSTATUS);
+
+/*
+ * #define CTI_DEBUG_INTEGRATION_CTRL to enable the access to the integration
+ * control registers. Normally only used to investigate connection data.
+ */
+/* #define CTI_DEBUG_INTEGRATION_CTRL */
+
+#ifdef CTI_DEBUG_INTEGRATION_CTRL
+
+/* macro to access RW registers with power check only (no enable check). */
+#define coresight_cti_reg_rw(name, offset)				\
+static ssize_t name##_show(struct device *dev,				\
+			   struct device_attribute *attr, char *buf)	\
+{									\
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);	\
+	u32 val = 0;							\
+	pm_runtime_get_sync(dev->parent);				\
+	spin_lock(&drvdata->spinlock);					\
+	if (drvdata->config.hw_powered)					\
+		val = readl_relaxed(drvdata->base + offset);		\
+	spin_unlock(&drvdata->spinlock);				\
+	pm_runtime_put_sync(dev->parent);				\
+	return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);		\
+}									\
+									\
+static ssize_t name##_store(struct device *dev,				\
+			    struct device_attribute *attr,		\
+			    const char *buf, size_t size)		\
+{									\
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);	\
+	unsigned long val = 0;						\
+	if (kstrtoul(buf, 0, &val))					\
+		return -EINVAL;						\
+									\
+	pm_runtime_get_sync(dev->parent);				\
+	spin_lock(&drvdata->spinlock);					\
+	if (drvdata->config.hw_powered)					\
+		cti_write_single_reg(drvdata, reg_offset, val);		\
+	spin_unlock(&drvdata->spinlock);				\
+	pm_runtime_put_sync(dev->parent);				\
+	return size;							\
+}									\
+static DEVICE_ATTR_RW(name)
+
+/* macro to access WO registers with power check only (no enable check). */
+#define coresight_cti_reg_wo(name, offset)				\
+static ssize_t name##_store(struct device *dev,				\
+			    struct device_attribute *attr,		\
+			    const char *buf, size_t size)		\
+{									\
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);	\
+	unsigned long val = 0;						\
+	if (kstrtoul(buf, 0, &val))					\
+		return -EINVAL;						\
+									\
+	pm_runtime_get_sync(dev->parent);				\
+	spin_lock(&drvdata->spinlock);					\
+	if (drvdata->config.hw_powered)					\
+		cti_write_single_reg(drvdata, reg_offset, val);		\
+	spin_unlock(&drvdata->spinlock);				\
+	pm_runtime_put_sync(dev->parent);				\
+	return size;							\
+}									\
+static DEVICE_ATTR_WO(name)
+
+coresight_cti_reg_rw(itchout, ITCHOUT);
+coresight_cti_reg_rw(ittrigout, ITTRIGOUT);
+coresight_cti_reg_rw(itctrl, CORESIGHT_ITCTRL);
+coresight_cti_reg_wo(itchinack, ITCHINACK);
+coresight_cti_reg_wo(ittriginack, ITTRIGINACK);
+coresight_cti_reg(ittrigin, ITTRIGIN);
+coresight_cti_reg(itchin, ITCHIN);
+coresight_cti_reg(itchoutack, ITCHOUTACK);
+coresight_cti_reg(ittrigoutack, ITTRIGOUTACK);
+
+#endif /* CTI_DEBUG_INTEGRATION_CTRL */
+
+static struct attribute *coresight_cti_regs_attrs[] = {
+	&dev_attr_inout_sel.attr,
+	&dev_attr_inen.attr,
+	&dev_attr_outen.attr,
+	&dev_attr_gate.attr,
+	&dev_attr_asicctl.attr,
+	&dev_attr_intack.attr,
+	&dev_attr_appset.attr,
+	&dev_attr_appclear.attr,
+	&dev_attr_apppulse.attr,
+	&dev_attr_triginstatus.attr,
+	&dev_attr_trigoutstatus.attr,
+	&dev_attr_chinstatus.attr,
+	&dev_attr_choutstatus.attr,
+#ifdef CTI_DEBUG_INTEGRATION_CTRL
+	&dev_attr_itctrl.attr,
+	&dev_attr_ittrigin.attr,
+	&dev_attr_itchin.attr,
+	&dev_attr_ittrigout.attr,
+	&dev_attr_itchout.attr,
+	&dev_attr_itchoutack.attr,
+	&dev_attr_ittrigoutack.attr,
+	&dev_attr_ittriginack.attr,
+	&dev_attr_itchinack.attr,
+#endif
+	NULL,
+};
+
+/* sysfs groups */
 static const struct attribute_group coresight_cti_group = {
 	.attrs = coresight_cti_attrs,
 };
@@ -118,8 +474,14 @@ static const struct attribute_group coresight_cti_mgmt_group = {
 	.name = "mgmt",
 };
 
+static const struct attribute_group coresight_cti_regs_group = {
+	.attrs = coresight_cti_regs_attrs,
+	.name = "regs",
+};
+
 const struct attribute_group *coresight_cti_groups[] = {
 	&coresight_cti_group,
 	&coresight_cti_mgmt_group,
+	&coresight_cti_regs_group,
 	NULL,
 };
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
index 7ae48bf62d17..b016b1e67fb1 100644
--- a/drivers/hwtracing/coresight/coresight-cti.c
+++ b/drivers/hwtracing/coresight/coresight-cti.c
@@ -149,6 +149,25 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
 	return 0;
 }
 
+void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value)
+{
+	CS_UNLOCK(drvdata->base);
+	writel_relaxed(value, drvdata->base + offset);
+	CS_LOCK(drvdata->base);
+}
+
+void cti_write_intack(struct device *dev, u32 ackval)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	/* write if enabled */
+	if (CTI_PWR_ENA(config))
+		cti_write_single_reg(drvdata, CTIINTACK, ackval);
+	spin_unlock(&drvdata->spinlock);
+}
+
 /*
  * Look at the HW DEVID register for some of the HW settings.
  * DEVID[15:8] - max number of in / out triggers.
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index e0d476533a82..73869fa8b313 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -180,7 +180,12 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
 					   int out_sigs);
 int cti_enable(struct coresight_device *csdev);
 int cti_disable(struct coresight_device *csdev);
+void cti_write_intack(struct device *dev, u32 ackval);
+void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
 struct coresight_platform_data *
 coresight_cti_get_platform_data(struct device *dev);
 
+/* cti powered and enabled */
+#define CTI_PWR_ENA(p_cfg) (p_cfg->hw_enabled && p_cfg->hw_powered)
+
 #endif  /* _CORESIGHT_CORESIGHT_CTI_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 04/14] coresight: cti: Add sysfs trigger / channel programming API
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (2 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-22 18:40   ` Mathieu Poirier
  2019-11-27 18:40   ` Suzuki Kuruppassery Poulose
  2019-11-19 23:19 ` [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions Mike Leach
                   ` (9 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Adds a user API to allow programming of CTI by trigger ID and
channel number. This will take the channel and trigger ID supplied
by the user and program the appropriate register values.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../hwtracing/coresight/coresight-cti-sysfs.c | 349 ++++++++++++++++++
 drivers/hwtracing/coresight/coresight-cti.c   | 147 ++++++++
 drivers/hwtracing/coresight/coresight-cti.h   |  32 ++
 3 files changed, 528 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 02d3ee0c1278..98de8a4768fc 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -464,6 +464,349 @@ static struct attribute *coresight_cti_regs_attrs[] = {
 	NULL,
 };
 
+/* CTI channel x-trigger programming */
+static int
+cti_trig_op_parse(struct device *dev, enum cti_chan_op op,
+		  enum cti_trig_dir dir, const char *buf, size_t size)
+{
+	u32 chan_idx;
+	u32 trig_idx;
+	int items, err = -EINVAL;
+
+	/* extract chan idx and trigger idx */
+	items = sscanf(buf, "%d %d", &chan_idx, &trig_idx);
+	if (items == 2) {
+		err = cti_channel_trig_op(dev, op, dir, chan_idx, trig_idx);
+		if (!err)
+			err = size;
+	}
+	return err;
+}
+
+static ssize_t trigin_attach_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	return cti_trig_op_parse(dev, CTI_CHAN_ATTACH, CTI_TRIG_IN,
+				 buf, size);
+}
+static DEVICE_ATTR_WO(trigin_attach);
+
+static ssize_t trigin_detach_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	return cti_trig_op_parse(dev, CTI_CHAN_DETACH, CTI_TRIG_IN,
+				 buf, size);
+}
+static DEVICE_ATTR_WO(trigin_detach);
+
+static ssize_t trigout_attach_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	return cti_trig_op_parse(dev, CTI_CHAN_ATTACH, CTI_TRIG_OUT,
+				 buf, size);
+}
+static DEVICE_ATTR_WO(trigout_attach);
+
+static ssize_t trigout_detach_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	return cti_trig_op_parse(dev, CTI_CHAN_DETACH, CTI_TRIG_OUT,
+				 buf, size);
+}
+static DEVICE_ATTR_WO(trigout_detach);
+
+
+static ssize_t chan_gate_enable_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t size)
+{
+	int err = 0, channel = 0;
+
+	if (kstrtoint(buf, 0, &channel))
+		return -EINVAL;
+
+	err = cti_channel_gate_op(dev, CTI_GATE_CHAN_ENABLE, channel);
+	return err ? err : size;
+}
+
+static ssize_t chan_gate_enable_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *cfg = &drvdata->config;
+	unsigned long ctigate_bitmask = cfg->ctigate;
+	int size = 0;
+
+	if (cfg->ctigate == 0)
+		size = scnprintf(buf, PAGE_SIZE, "\n");
+	else
+		size = bitmap_print_to_pagebuf(true, buf, &ctigate_bitmask,
+					       cfg->nr_ctm_channels);
+	return size;
+}
+static DEVICE_ATTR_RW(chan_gate_enable);
+
+static ssize_t chan_gate_disable_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t size)
+{
+	int err = 0, channel = 0;
+
+	if (kstrtoint(buf, 0, &channel))
+		return -EINVAL;
+
+	err = cti_channel_gate_op(dev, CTI_GATE_CHAN_DISABLE, channel);
+	return err ? err : size;
+}
+static DEVICE_ATTR_WO(chan_gate_disable);
+
+static int
+chan_op_parse(struct device *dev, enum cti_chan_set_op op, const char *buf)
+{
+	int err = 0, channel = 0;
+
+	if (kstrtoint(buf, 0, &channel))
+		return -EINVAL;
+
+	err = cti_channel_setop(dev, op, channel);
+	return err;
+
+}
+
+static ssize_t chan_set_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	int err = chan_op_parse(dev, CTI_CHAN_SET, buf);
+
+	return err ? err : size;
+}
+static DEVICE_ATTR_WO(chan_set);
+
+static ssize_t chan_clear_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	int err = chan_op_parse(dev, CTI_CHAN_CLR, buf);
+
+	return err ? err : size;
+}
+static DEVICE_ATTR_WO(chan_clear);
+
+static ssize_t chan_pulse_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	int err = chan_op_parse(dev, CTI_CHAN_PULSE, buf);
+
+	return err ? err : size;
+}
+static DEVICE_ATTR_WO(chan_pulse);
+
+static ssize_t trig_filter_enable_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	u32 val;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	spin_lock(&drvdata->spinlock);
+	val = drvdata->config.trig_filter_enable;
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t trig_filter_enable_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t size)
+{
+	unsigned long val;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	drvdata->config.trig_filter_enable = !!val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(trig_filter_enable);
+
+static ssize_t trigout_filtered_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *cfg = &drvdata->config;
+	int size = 0, nr_trig_max = cfg->nr_trig_max;
+	unsigned long mask = cfg->trig_out_filter;
+
+	if (mask)
+		size = bitmap_print_to_pagebuf(true, buf, &mask, nr_trig_max);
+	return size;
+}
+static DEVICE_ATTR_RO(trigout_filtered);
+
+/* clear all xtrigger / channel programming */
+static ssize_t chan_xtrigs_reset_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t size)
+{
+	int i;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+
+	/* clear the CTI trigger / channel programming registers */
+	for (i = 0; i < config->nr_trig_max; i++) {
+		config->ctiinen[i] = 0;
+		config->ctiouten[i] = 0;
+	}
+
+	/* clear the other regs */
+	config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
+	config->asicctl = 0;
+	config->ctiappset = 0;
+	config->ctiinout_sel = 0;
+	config->xtrig_rchan_sel = 0;
+
+	/* if enabled then write through */
+	if (CTI_PWR_ENA(config))
+		cti_write_all_hw_regs(drvdata);
+
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_WO(chan_xtrigs_reset);
+
+/*
+ * Write to select a channel to view, read to display the
+ * cross triggers for the selected channel.
+ */
+static ssize_t chan_xtrigs_view_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+	if (val > (drvdata->config.nr_ctm_channels - 1))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	drvdata->config.xtrig_rchan_sel = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+
+static ssize_t chan_xtrigs_view_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *cfg = &drvdata->config;
+	int used = 0, reg_idx;
+	int buf_sz = PAGE_SIZE;
+	u32 chan_mask = BIT(cfg->xtrig_rchan_sel);
+
+	used += scnprintf(buf, buf_sz, "[%d] IN: ", cfg->xtrig_rchan_sel);
+	for (reg_idx = 0;
+	     reg_idx < drvdata->config.nr_trig_max;
+	     reg_idx++) {
+		if (chan_mask & cfg->ctiinen[reg_idx]) {
+			used += scnprintf(buf + used, buf_sz - used, "%d ",
+					  reg_idx);
+		}
+	}
+
+	used += scnprintf(buf + used, buf_sz - used, "OUT: ");
+	for (reg_idx = 0;
+	     reg_idx < drvdata->config.nr_trig_max;
+	     reg_idx++) {
+		if (chan_mask & cfg->ctiouten[reg_idx]) {
+			used += scnprintf(buf + used, buf_sz - used, "%d ",
+					  reg_idx);
+		}
+	}
+	used += scnprintf(buf + used, buf_sz - used, "\n");
+	return used;
+}
+static DEVICE_ATTR_RW(chan_xtrigs_view);
+
+static ssize_t print_chan_list(struct device *dev,
+			       char *buf, bool inuse)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+	int size, i;
+	unsigned long inuse_bits = 0, chan_mask;
+
+	/* scan regs to get bitmap of channels in use. */
+	spin_lock(&drvdata->spinlock);
+	for (i = 0; i < config->nr_trig_max; i++) {
+		inuse_bits |= config->ctiinen[i];
+		inuse_bits |= config->ctiouten[i];
+	}
+	spin_unlock(&drvdata->spinlock);
+
+	/* inverse bits if printing free channels */
+	if (!inuse)
+		inuse_bits = ~inuse_bits;
+
+	/* list of channels, or 'none' */
+	chan_mask = GENMASK(config->nr_ctm_channels - 1, 0);
+	if (inuse_bits & chan_mask)
+		size = bitmap_print_to_pagebuf(true, buf, &inuse_bits,
+					       config->nr_ctm_channels);
+	else
+		size = scnprintf(buf, PAGE_SIZE, "\n");
+	return size;
+}
+
+static ssize_t chan_inuse_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	return print_chan_list(dev, buf, true);
+}
+static DEVICE_ATTR_RO(chan_inuse);
+
+static ssize_t chan_free_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	return print_chan_list(dev, buf, false);
+}
+static DEVICE_ATTR_RO(chan_free);
+
+static struct attribute *coresight_cti_channel_attrs[] = {
+	&dev_attr_trigin_attach.attr,
+	&dev_attr_trigin_detach.attr,
+	&dev_attr_trigout_attach.attr,
+	&dev_attr_trigout_detach.attr,
+	&dev_attr_trig_filter_enable.attr,
+	&dev_attr_trigout_filtered.attr,
+	&dev_attr_chan_gate_enable.attr,
+	&dev_attr_chan_gate_disable.attr,
+	&dev_attr_chan_set.attr,
+	&dev_attr_chan_clear.attr,
+	&dev_attr_chan_pulse.attr,
+	&dev_attr_chan_inuse.attr,
+	&dev_attr_chan_free.attr,
+	&dev_attr_chan_xtrigs_view.attr,
+	&dev_attr_chan_xtrigs_reset.attr,
+	NULL,
+};
+
 /* sysfs groups */
 static const struct attribute_group coresight_cti_group = {
 	.attrs = coresight_cti_attrs,
@@ -479,9 +822,15 @@ static const struct attribute_group coresight_cti_regs_group = {
 	.name = "regs",
 };
 
+static const struct attribute_group coresight_cti_channels_group = {
+	.attrs = coresight_cti_channel_attrs,
+	.name = "channels",
+};
+
 const struct attribute_group *coresight_cti_groups[] = {
 	&coresight_cti_group,
 	&coresight_cti_mgmt_group,
 	&coresight_cti_regs_group,
+	&coresight_cti_channels_group,
 	NULL,
 };
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
index b016b1e67fb1..369488dd7b8e 100644
--- a/drivers/hwtracing/coresight/coresight-cti.c
+++ b/drivers/hwtracing/coresight/coresight-cti.c
@@ -293,6 +293,153 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
 	return ret;
 }
 
+/** cti channel api **/
+/* attach/detach channel from trigger - write through if enabled. */
+int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
+			enum cti_trig_dir direction, u32 channel_idx,
+			u32 trigger_idx)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+	u32 trig_bitmask;
+	u32 chan_bitmask;
+	u32 reg_value;
+	int reg_offset;
+
+	/* ensure indexes in range */
+	if ((channel_idx >= config->nr_ctm_channels) ||
+	   (trigger_idx >= config->nr_trig_max))
+		return -EINVAL;
+
+	trig_bitmask = BIT(trigger_idx);
+
+	/* ensure registered triggers and not out filtered */
+	if (direction == CTI_TRIG_IN)	{
+		if (!(trig_bitmask & config->trig_in_use))
+			return -EINVAL;
+	} else {
+		if (!(trig_bitmask & config->trig_out_use))
+			return -EINVAL;
+
+		if ((config->trig_filter_enable) &&
+		    (config->trig_out_filter & trig_bitmask))
+			return -EINVAL;
+	}
+
+	/* update the local register values */
+	chan_bitmask = BIT(channel_idx);
+	reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
+		      CTIOUTEN(trigger_idx));
+
+	spin_lock(&drvdata->spinlock);
+
+	/* read - modify write - the trigger / channel enable value */
+	reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] :
+		     config->ctiouten[trigger_idx];
+	if (op == CTI_CHAN_ATTACH)
+		reg_value |= chan_bitmask;
+	else
+		reg_value &= ~chan_bitmask;
+
+	/* write local copy */
+	if (direction == CTI_TRIG_IN)
+		config->ctiinen[trigger_idx] = reg_value;
+	else
+		config->ctiouten[trigger_idx] = reg_value;
+
+	/* write through if enabled */
+	if (CTI_PWR_ENA(config))
+		cti_write_single_reg(drvdata, reg_offset, reg_value);
+	spin_unlock(&drvdata->spinlock);
+	return 0;
+}
+
+int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
+			u32 channel_idx)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+	u32 chan_bitmask;
+	u32 reg_value;
+	int err = 0;
+
+	if (channel_idx >= config->nr_ctm_channels)
+		return -EINVAL;
+
+	chan_bitmask = BIT(channel_idx);
+
+	spin_lock(&drvdata->spinlock);
+	reg_value = config->ctigate;
+	switch (op) {
+	case CTI_GATE_CHAN_ENABLE:
+		reg_value |= chan_bitmask;
+		break;
+
+	case CTI_GATE_CHAN_DISABLE:
+		reg_value &= ~chan_bitmask;
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+	if (err == 0) {
+		config->ctigate = reg_value;
+		if (CTI_PWR_ENA(config))
+			cti_write_single_reg(drvdata, CTIGATE, reg_value);
+	}
+	spin_unlock(&drvdata->spinlock);
+	return err;
+}
+
+int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
+		      u32 channel_idx)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *config = &drvdata->config;
+	u32 chan_bitmask;
+	u32 reg_value;
+	u32 reg_offset;
+	int err = 0;
+
+	if (channel_idx >= config->nr_ctm_channels)
+		return -EINVAL;
+
+	chan_bitmask = BIT(channel_idx);
+
+	spin_lock(&drvdata->spinlock);
+	reg_value = config->ctiappset;
+	switch (op) {
+	case CTI_CHAN_SET:
+		config->ctiappset |= chan_bitmask;
+		reg_value  = config->ctiappset;
+		reg_offset = CTIAPPSET;
+		break;
+
+	case CTI_CHAN_CLR:
+		config->ctiappset &= ~chan_bitmask;
+		reg_value = chan_bitmask;
+		reg_offset = CTIAPPCLEAR;
+		break;
+
+	case CTI_CHAN_PULSE:
+		config->ctiappset &= ~chan_bitmask;
+		reg_value = chan_bitmask;
+		reg_offset = CTIAPPPULSE;
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	if ((err == 0) && CTI_PWR_ENA(config))
+		cti_write_single_reg(drvdata, reg_offset, reg_value);
+	spin_unlock(&drvdata->spinlock);
+
+	return err;
+}
+
 /** cti ect operations **/
 int cti_enable(struct coresight_device *csdev)
 {
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index 73869fa8b313..9a22f6fcad65 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -168,6 +168,30 @@ struct cti_drvdata {
 	void (*csdev_release)(struct device *dev);
 };
 
+/*
+ * Channel operation types.
+ */
+enum cti_chan_op {
+	CTI_CHAN_ATTACH,
+	CTI_CHAN_DETACH,
+};
+
+enum cti_trig_dir {
+	CTI_TRIG_IN,
+	CTI_TRIG_OUT,
+};
+
+enum cti_chan_gate_op {
+	CTI_GATE_CHAN_ENABLE,
+	CTI_GATE_CHAN_DISABLE,
+};
+
+enum cti_chan_set_op {
+	CTI_CHAN_SET,
+	CTI_CHAN_CLR,
+	CTI_CHAN_PULSE,
+};
+
 /* private cti driver fns & vars */
 extern const struct attribute_group *coresight_cti_groups[];
 int cti_add_default_connection(struct device *dev,
@@ -180,8 +204,16 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
 					   int out_sigs);
 int cti_enable(struct coresight_device *csdev);
 int cti_disable(struct coresight_device *csdev);
+void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
 void cti_write_intack(struct device *dev, u32 ackval);
 void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
+int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
+			enum cti_trig_dir direction, u32 channel_idx,
+			u32 trigger_idx);
+int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
+			u32 channel_idx);
+int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
+		      u32 channel_idx);
 struct coresight_platform_data *
 coresight_cti_get_platform_data(struct device *dev);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions.
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (3 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 04/14] coresight: cti: Add sysfs trigger / channel programming API Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-20 19:06   ` Mathieu Poirier
                     ` (2 more replies)
  2019-11-19 23:19 ` [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI Mike Leach
                   ` (8 subsequent siblings)
  13 siblings, 3 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Adds new coresight-cti.yaml file describing the bindings required to define
CTI in the device trees.

Adds an include file to dt-bindings/arm to define constants describing
common signal functionality used in CoreSight and generic usage.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../bindings/arm/coresight-cti.yaml           | 303 ++++++++++++++++++
 .../devicetree/bindings/arm/coresight.txt     |   7 +
 MAINTAINERS                                   |   2 +
 include/dt-bindings/arm/coresight-cti-dt.h    |  37 +++
 4 files changed, 349 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/coresight-cti.yaml
 create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h

diff --git a/Documentation/devicetree/bindings/arm/coresight-cti.yaml b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
new file mode 100644
index 000000000000..882c72f1c798
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
@@ -0,0 +1,303 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright 2019 Linaro Ltd.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/coresight-cti.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ARM Coresight Cross Trigger Interface (CTI) device.
+
+description: |
+  The CoreSight Embedded Cross Trigger (ECT) consists of CTI devices connected
+  to one or more CoreSight components and/or a CPU, with CTIs interconnected in
+  a star topology via the CTM (which is not programmable). The ECT components
+  are not part of the trace generation data path and are thus not part of the
+  CoreSight graph described in the general CoreSight bindings file
+  coresight.txt.
+
+  The CTI component properties define the connections between the individual
+  CTI and the components it is directly connected to, consisting of input and
+  output hardware trigger signals. CTIs can have a maximum number of input and
+  output hardware trigger signals (8 each for v1 CTI, 32 each for v2 CTI). The
+  number is defined at design time, the maximum of each defined in the DEVID
+  register.
+
+  CTIs are interconnected in a star topology via the CTM, using a number of
+  programmable channels usually 4, but again implementation defined and
+  described in the DEVID register. The star topology is not required to be
+  described in the bindings as the actual connections are software
+  programmable.
+
+  In general the connections between CTI and components via the trigger signals
+  are implementation defined, other than when v8 core and ETM is present.
+  The v8 architecture defines the required signal connections between CPU core
+  and CTI, and ETM and CTI, if the ETM if present.
+
+  When only minimal information is available for the CTI trigger connections,
+  then a minimal driver binding can be declare with no explicit trigger
+  signals. This will result in the using the DEVID register to set the
+  input and output triggers and channels in use. Any user / client
+  application will require additional information on the connections
+  between the CTI and other components for correct operation. This minimal
+  binding may be used when using the Integration Control registers to
+  discover connections between CTI and other CoreSight components,
+
+  Certain triggers between CoreSight devices and the CTI have specific types
+  and usages. These can be defined along with the signal indexes with the
+  constants defined in <dt-bindings/arm/coresight-cti-dt.h>
+
+  For example a CTI connected to a core will usually have a DBGREQ signal. This
+  is defined in the binding as type PE_EDBGREQ. These types will appear in an
+  optional array alongside the signal indexes. Omitting types will default all
+  signals to GEN_IO.
+
+  Note that some hardware trigger signals can be connected to non-CoreSight
+  components (e.g. UART etc) depending on hardware implementation.
+
+maintainers:
+  - Mike Leach <mike.leach@linaro.org>
+
+allOf:
+  - $ref: /schemas/arm/primecell.yaml#
+
+# Need a custom select here or 'arm,primecell' will match on lots of nodes
+select:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - arm,coresight-cti
+  required:
+    - compatible
+
+properties:
+  $nodename:
+    pattern: "^cti(@[0-9a-f,]+)*$"
+  compatible:
+    items:
+      - const: arm,coresight-cti
+      - const: arm,primecell
+
+  reg:
+    items:
+      - description: device programming registers
+
+  arm,cti-v8-arch:
+    type: boolean
+    description:
+      This CTI follows the v8 architecturally mandated layout for a CTI.
+      Bindings declaring this must declare a cpu, and optionally a single
+      arm,cs-dev-assoc may be present to define an attached ETM. No additional
+      trig-conns nodes are permitted. The driver will build a connection model
+      according to architectural requirements. This will include a filter on
+      the CPU dbgreq signal as described above.
+
+  cpu:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/phandle
+    description: Handle to cpu this device is associated with.
+
+  arm,cti-ctm-id:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Defines the CTM this CTI is connected to, in large systems with multiple
+      separate CTI/CTM nets. Typically multi-socket systems where the CTM is
+      propagated between sockets.
+
+  arm,cs-dev-assoc:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      defines a phandle reference to an associated CoreSight trace device.
+      When the associated trace device is enabled, then the respective CTI
+      will be enabled. Use in a trig-conns node, or in CTI base node when
+      arm,cti-v8-arch present. If the associated device has not been registered
+      then the node name will be stored as the connection name for later
+      resolution. If the associated device is not a CoreSight device or not
+      registered then the node name will remain the connection name and
+      automatic enabling will not occur.
+
+patternProperties:
+  '^trig_conns@[0-9]+$':
+    type: object
+    description:
+      A trigger connections child node which describes the trigger signals
+      between this CTI and another hardware device. This device may be a CPU,
+      CoreSight device, any other hardware device or simple external IO lines.
+      The connection may have both input and output triggers, or only one or the
+      other.
+
+    properties:
+
+      arm,trig-in-sigs:
+        allOf:
+          - $ref: /schemas/types.yaml#/definitions/uint32-array
+        minItems: 1
+        maxItems: 32
+        description:
+          List of CTI trigger in signal numbers in use by a trig-conns node.
+
+      arm,trig-in-types:
+        allOf:
+          - $ref: /schemas/types.yaml#/definitions/uint32-array
+        minItems: 1
+        maxItems: 32
+        description:
+          List of constants representing the types for the CTI trigger in
+          signals. Types in this array match to the corresponding signal in the
+          arm,trig-in-sigs array. If the -types array is smaller, or omitted
+          completely, then the types will default to GEN_IO.
+
+      arm,trig-out-sigs:
+        allOf:
+          - $ref: /schemas/types.yaml#/definitions/uint32-array
+        minItems: 1
+        maxItems: 32
+        description:
+          List of CTI trigger out signal numbers in use by a trig-conns node.
+
+      arm,trig-out-types:
+        allOf:
+          - $ref: /schemas/types.yaml#/definitions/uint32-array
+        minItems: 1
+        maxItems: 32
+        description:
+          List of constants representing the types for the CTI trigger out
+          signals. Types in this array match to the corresponding signal
+          in the arm,trig-out-sigs array. If the "-types" array is smaller,
+          or omitted completely, then the types will default to GEN_IO.
+
+      arm,trig-filters:
+        allOf:
+          - $ref: /schemas/types.yaml#/definitions/uint32-array
+        minItems: 1
+        maxItems: 32
+        description:
+          List of CTI trigger out signals that will be blocked from becoming
+          active, unless filtering is disabled on the driver.
+
+      arm,trig-conn-name:
+        allOf:
+          - $ref: /schemas/types.yaml#/definitions/string
+        description:
+          Defines a connection name that will be displayed, if the cpu or
+          arm,cs-dev-assoc properties are not being used in this connection.
+          Principle use for CTI that are connected to non-CoreSight devices, or
+          external IO.
+
+    anyOf:
+      - required:
+        - arm,trig-in-sigs
+      - required:
+        - arm,trig-out-sigs
+    oneOf:
+      - required:
+        - arm,trig-conn-name
+      - required:
+        - cpu
+      - required:
+        - arm,cs-dev-assoc
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+
+examples:
+  # minimum CTI definition. DEVID register used to set number of triggers.
+  - |
+    cti@20020000 {
+      compatible = "arm,coresight-cti", "arm,primecell";
+      reg = <0x20020000 0x1000>;
+
+      clocks = <&soc_smc50mhz>;
+      clock-names = "apb_pclk";
+    };
+  #  v8 architecturally defined CTI - CPU + ETM connections generated by the
+  #  driver according to the v8 architecture specification.
+  - |
+    cti@859000 {
+      compatible = "arm,coresight-cti", "arm,primecell";
+      reg = <0x859000 0x1000>;
+
+      clocks = <&soc_smc50mhz>;
+      clock-names = "apb_pclk";
+
+      arm,cti-v8-arch;
+      cpu = <&CPU1>;
+      arm,cs-dev-assoc = <&etm1>;
+    };
+  # Implementation defined CTI - CPU + ETM connections explicitly defined..
+  # Shows use of type constants from dt-bindings/arm/coresight-cti-dt.h
+  - |
+    #include <dt-bindings/arm/coresight-cti-dt.h>
+
+    cti@858000 {
+      compatible = "arm,coresight-cti", "arm,primecell";
+      reg = <0x858000 0x1000>;
+
+      clocks = <&soc_smc50mhz>;
+      clock-names = "apb_pclk";
+
+      arm,cti-ctm-id = <1>;
+
+      trig-conns@0 {
+            arm,trig-in-sigs = <4 5 6 7>;
+            arm,trig-in-types = <ETM_EXTOUT
+                                 ETM_EXTOUT
+                                 ETM_EXTOUT
+                                 ETM_EXTOUT>;
+            arm,trig-out-sigs = <4 5 6 7>;
+            arm,trig-out-types = <ETM_EXTIN
+                                  ETM_EXTIN
+                                  ETM_EXTIN
+                                  ETM_EXTIN>;
+            arm,cs-dev-assoc = <&etm0>;
+      };
+
+      trig-conns@1 {
+            cpu = <&CPU0>;
+            arm,trig-in-sigs = <0 1>;
+            arm,trig-in-types = <PE_DBGTRIGGER
+                                 PE_PMUIRQ>;
+            arm,trig-out-sigs=<0 1 2 >;
+            arm,trig-out-types = <PE_EDBGREQ
+                                  PE_DBGRESTART
+                                  PE_CTIIRQ>;
+
+            arm,trig-filters = <0>;
+      };
+    };
+  # Implementation defined CTI - none CoreSight component connections.
+  - |
+    cti@20110000 {
+      compatible = "arm,coresight-cti", "arm,primecell";
+      reg = <0 0x20110000 0 0x1000>;
+
+      clocks = <&soc_smc50mhz>;
+      clock-names = "apb_pclk";
+
+      trig-conns@0 {
+        arm,trig-in-sigs=<0>;
+        arm,trig-in-types=<GEN_INTREQ>;
+        arm,trig-out-sigs=<0>;
+        arm,trig-out-types=<GEN_HALTREQ>;
+        arm,trig-conn-name = "sys_profiler";
+      };
+
+      trig-conns@1 {
+        arm,trig-out-sigs=<2 3>;
+        arm,trig-out-types=<GEN_HALTREQ GEN_RESTARTREQ>;
+        arm,trig-conn-name = "watchdog";
+      };
+
+      trig-conns@2 {
+        arm,trig-in-sigs=<1 6>;
+        arm,trig-in-types=<GEN_HALTREQ GEN_RESTARTREQ>;
+        arm,trig-conn-name = "g_counter";
+      };
+    };
+
+...
\ No newline at end of file
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index d02c42d21f2f..846f6daae71b 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -45,6 +45,10 @@ its hardware characteristcs.
 		- Coresight Address Translation Unit (CATU)
 			"arm,coresight-catu", "arm,primecell";
 
+		- Coresight Cross Trigger Interface (CTI):
+			"arm,coresight-cti", "arm,primecell";
+			See coresight-cti.yaml for full CTI definitions.
+
 	* reg: physical base address and length of the register
 	  set(s) of the component.
 
@@ -72,6 +76,9 @@ its hardware characteristcs.
 	* reg-names: the only acceptable values are "stm-base" and
 	  "stm-stimulus-base", each corresponding to the areas defined in "reg".
 
+* Required properties for Coresight Cross Trigger Interface (CTI)
+	See coresight-cti.yaml for full CTI definitions.
+
 * Required properties for devices that don't show up on the AMBA bus, such as
   non-configurable replicators and non-configurable funnels:
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 9de89d75dbcc..8d01a74068f7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1608,9 +1608,11 @@ R:	Suzuki K Poulose <suzuki.poulose@arm.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	drivers/hwtracing/coresight/*
+F:	include/dt-bindings/arm/coresight-cti-dt.h
 F:	Documentation/trace/coresight/*
 F:	Documentation/devicetree/bindings/arm/coresight.txt
 F:	Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt
+F:	Documentation/devicetree/bindings/arm/coresight-cti.yaml
 F:	Documentation/ABI/testing/sysfs-bus-coresight-devices-*
 F:	tools/perf/arch/arm/util/pmu.c
 F:	tools/perf/arch/arm/util/auxtrace.c
diff --git a/include/dt-bindings/arm/coresight-cti-dt.h b/include/dt-bindings/arm/coresight-cti-dt.h
new file mode 100644
index 000000000000..61e7bdf8ea6e
--- /dev/null
+++ b/include/dt-bindings/arm/coresight-cti-dt.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides constants for the defined trigger signal
+ * types on CoreSight CTI.
+ */
+
+#ifndef _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
+#define _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
+
+#define GEN_IO		0
+#define GEN_INTREQ	1
+#define GEN_INTACK	2
+#define GEN_HALTREQ	3
+#define GEN_RESTARTREQ	4
+#define PE_EDBGREQ	5
+#define PE_DBGRESTART	6
+#define PE_CTIIRQ	7
+#define PE_PMUIRQ	8
+#define PE_DBGTRIGGER	9
+#define ETM_EXTOUT	10
+#define ETM_EXTIN	11
+#define SNK_FULL	12
+#define SNK_ACQCOMP	13
+#define SNK_FLUSHCOMP	14
+#define SNK_FLUSHIN	15
+#define SNK_TRIGIN	16
+#define STM_ASYNCOUT	17
+#define STM_TOUT_SPTE	18
+#define STM_TOUT_SW	19
+#define STM_TOUT_HETE	20
+#define STM_HWEVENT	21
+#define ELA_TSTART	22
+#define ELA_TSTOP	23
+#define ELA_DBGREQ	24
+#define CTI_TRIG_MAX	25
+
+#endif /*_DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H */
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (4 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-25 19:00   ` Mathieu Poirier
  2019-11-29 11:33   ` Suzuki Kuruppassery Poulose
  2019-11-19 23:19 ` [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI Mike Leach
                   ` (7 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

The v8 architecture defines the relationship between a PE, its optional ETM
and a CTI. Unlike non-architectural CTIs which are implementation defined,
this has a fixed set of connections which can therefore be represented as a
simple tag in the device tree.

This patch defines the tags needed to create an entry for this PE/ETM/CTI
relationship, and provides functionality to implement the connection model
in the CTI driver.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../coresight/coresight-cti-platform.c        | 205 ++++++++++++++++++
 1 file changed, 205 insertions(+)

diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
index 665be86c585d..790dd30b85f5 100644
--- a/drivers/hwtracing/coresight/coresight-cti-platform.c
+++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
@@ -3,10 +3,208 @@
  * Copyright (c) 2019, The Linaro Limited. All rights reserved.
  */
 
+#include <dt-bindings/arm/coresight-cti-dt.h>
 #include <linux/of.h>
 
 #include "coresight-cti.h"
 
+/* Number of CTI signals in the v8 architecturally defined connection */
+#define NR_V8PE_IN_SIGS		2
+#define NR_V8PE_OUT_SIGS	3
+#define NR_V8ETM_INOUT_SIGS	4
+
+/* CTI device tree connection property keywords */
+#define CTI_DT_V8ARCH		"arm,cti-v8-arch"
+#define CTI_DT_CSDEV_ASSOC	"arm,cs-dev-assoc"
+
+/*
+ * Find a registered coresight device from a device fwnode.
+ * The node info is associated with the AMBA parent, but the
+ * csdev keeps a copy so iterate round the coresight bus to
+ * find the device.
+ */
+static struct coresight_device *
+cti_get_assoc_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
+{
+	struct device *dev;
+	struct coresight_device *csdev = NULL;
+
+	dev = bus_find_device_by_fwnode(&coresight_bustype, r_fwnode);
+	if (dev) {
+		csdev = to_coresight_device(dev);
+		put_device(dev);
+	}
+	return csdev;
+}
+
+#ifdef CONFIG_OF
+/*
+ * CTI can be bound to a CPU, or a system device.
+ * CPU can be declared at the device top level or in a connections node
+ * so need to check relative to node not device.
+ */
+static int of_cti_get_cpu_at_node(const struct device_node *node)
+{
+	int cpu;
+	struct device_node *dn;
+
+	if (node == NULL)
+		return -1;
+
+	dn = of_parse_phandle(node, "cpu", 0);
+	/* CTI affinity defaults to no cpu */
+	if (!dn)
+		return -1;
+	cpu = of_cpu_node_to_id(dn);
+	of_node_put(dn);
+
+	/* No Affinity  if no cpu nodes are found */
+	return (cpu < 0) ? -1 : cpu;
+}
+
+static const char *of_cti_get_node_name(const struct device_node *node)
+{
+	if (node)
+		return node->full_name;
+	return "unknown";
+}
+#else
+static int of_cti_get_cpu_at_node(const struct device_node *node)
+{
+	return -1;
+}
+
+static const char *of_cti_get_node_name(const struct device_node *node)
+{
+	return "unknown";
+}
+#endif
+
+static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
+{
+	if (is_of_node(fwnode))
+		return of_cti_get_cpu_at_node(to_of_node(fwnode));
+	return -1;
+}
+
+static const char *cti_plat_get_node_name(struct fwnode_handle *fwnode)
+{
+	if (is_of_node(fwnode))
+		return of_cti_get_node_name(to_of_node(fwnode));
+	return "unknown";
+}
+
+static int cti_plat_create_v8_etm_connection(struct device *dev,
+					     struct cti_drvdata *drvdata)
+{
+	int ret = -ENOMEM, i;
+	struct fwnode_handle *root_fwnode, *cs_fwnode;
+	const char *assoc_name = NULL;
+	struct coresight_device *csdev;
+	struct cti_trig_con *tc = NULL;
+
+	root_fwnode = dev_fwnode(dev);
+	if (IS_ERR_OR_NULL(root_fwnode))
+		return -EINVAL;
+
+	/* Can optionally have an etm node - return if not  */
+	cs_fwnode = fwnode_find_reference(root_fwnode, CTI_DT_CSDEV_ASSOC, 0);
+	if (IS_ERR_OR_NULL(cs_fwnode))
+		return 0;
+
+	/* allocate memory */
+	tc = cti_allocate_trig_con(dev, NR_V8ETM_INOUT_SIGS,
+				   NR_V8ETM_INOUT_SIGS);
+	if (!tc)
+		goto create_v8_etm_out;
+
+	/* build connection data */
+	tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */
+	tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */
+
+	/*
+	 * The EXTOUT type signals from the ETM are connected to a set of input
+	 * triggers on the CTI, the EXTIN being connected to output triggers.
+	 */
+	for (i = 0; i < NR_V8ETM_INOUT_SIGS; i++) {
+		tc->con_in->sig_types[i] = ETM_EXTOUT;
+		tc->con_out->sig_types[i] = ETM_EXTIN;
+	}
+
+	/*
+	 * We look to see if the ETM coresight device associated with this
+	 * handle has been registered with the system - i.e. probed before
+	 * this CTI. If so csdev will be non NULL and we can use the device
+	 * name and pass the csdev to the connection entry function where
+	 * the association will be recorded.
+	 * If not, then simply record the name in the connection data, the
+	 * probing of the ETM will call into the CTI driver API to update the
+	 * association then.
+	 */
+	csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
+	if (csdev)
+		assoc_name = dev_name(&csdev->dev);
+	else
+		assoc_name = cti_plat_get_node_name(cs_fwnode);
+	ret = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name);
+
+create_v8_etm_out:
+	fwnode_handle_put(cs_fwnode);
+	return ret;
+}
+
+/*
+ * Create an architecturally defined v8 connection
+ * must have a cpu, can have an ETM.
+ */
+static int cti_plat_create_v8_connections(struct device *dev,
+					  struct cti_drvdata *drvdata)
+{
+	struct cti_device *cti_dev = &drvdata->ctidev;
+	struct cti_trig_con *tc = NULL;
+	int cpuid = 0;
+	char cpu_name_str[16];
+	int ret = -ENOMEM;
+
+	/* Must have a cpu node */
+	cpuid = cti_plat_get_cpu_at_node(dev_fwnode(dev));
+	if (cpuid < 0) {
+		dev_warn(dev, "CTI v8 DT binding no cpu\n");
+		return -EINVAL;
+	}
+	cti_dev->cpu = cpuid;
+
+	/* Allocate the v8 cpu connection memory */
+	tc = cti_allocate_trig_con(dev, NR_V8PE_IN_SIGS, NR_V8PE_OUT_SIGS);
+	if (!tc)
+		goto of_create_v8_out;
+
+	/* Set the v8 PE CTI connection data */
+	tc->con_in->used_mask = 0x3; /* sigs <0 1> */
+	tc->con_in->sig_types[0] = PE_DBGTRIGGER;
+	tc->con_in->sig_types[1] = PE_PMUIRQ;
+	tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */
+	tc->con_out->sig_types[0] = PE_EDBGREQ;
+	tc->con_out->sig_types[1] = PE_DBGRESTART;
+	tc->con_out->sig_types[2] = PE_CTIIRQ;
+	scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid);
+
+	ret = cti_add_connection_entry(dev, drvdata, tc, NULL, cpu_name_str);
+	if (ret)
+		goto of_create_v8_out;
+
+	/* Create the v8 ETM associated connection */
+	ret = cti_plat_create_v8_etm_connection(dev, drvdata);
+	if (ret)
+		goto of_create_v8_out;
+
+	/* filter pe_edbgreq - PE trigout sig <0> */
+	drvdata->config.trig_out_filter |= 0x1;
+
+of_create_v8_out:
+	return ret;
+}
+
 /* get the hardware configuration & connection data. */
 int cti_plat_get_hw_data(struct device *dev,
 			 struct cti_drvdata *drvdata)
@@ -14,6 +212,13 @@ int cti_plat_get_hw_data(struct device *dev,
 	int rc = 0;
 	struct cti_device *cti_dev = &drvdata->ctidev;
 
+	/* check for a v8 architectural CTI device */
+	if (device_property_read_bool(dev, CTI_DT_V8ARCH)) {
+		rc = cti_plat_create_v8_connections(dev, drvdata);
+		if (rc)
+			return rc;
+	}
+
 	/* if no connections, just add a single default based on max IN-OUT */
 	if (cti_dev->nr_trig_con == 0)
 		rc = cti_add_default_connection(dev, drvdata);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI.
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (5 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-25 21:22   ` Mathieu Poirier
  2019-11-29 14:18   ` Suzuki Kuruppassery Poulose
  2019-11-19 23:19 ` [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices Mike Leach
                   ` (6 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Adds support for CTIs whose connections are implementation defined at
hardware design time, and not constrained by v8 architecture.

These CTIs have no standard connection setup, all the settings have to
be defined in the device tree files. The patch creates a set of connections
and trigger signals based on the information provided.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../coresight/coresight-cti-platform.c        | 250 +++++++++++++++++-
 .../hwtracing/coresight/coresight-cti-sysfs.c |  11 +
 2 files changed, 257 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
index 790dd30b85f5..9c1ff432b487 100644
--- a/drivers/hwtracing/coresight/coresight-cti-platform.c
+++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
@@ -13,9 +13,19 @@
 #define NR_V8PE_OUT_SIGS	3
 #define NR_V8ETM_INOUT_SIGS	4
 
+/* CTI device tree trigger connection node keyword */
+#define CTI_DT_CONNS		"trig-conns"
+
 /* CTI device tree connection property keywords */
 #define CTI_DT_V8ARCH		"arm,cti-v8-arch"
 #define CTI_DT_CSDEV_ASSOC	"arm,cs-dev-assoc"
+#define CTI_DT_TRIGIN_SIGS	"arm,trig-in-sigs"
+#define CTI_DT_TRIGOUT_SIGS	"arm,trig-out-sigs"
+#define CTI_DT_TRIGIN_TYPES	"arm,trig-in-types"
+#define CTI_DT_TRIGOUT_TYPES	"arm,trig-out-types"
+#define CTI_DT_FILTER_OUT_SIGS	"arm,trig-filters"
+#define CTI_DT_CONN_NAME	"arm,trig-conn-name"
+#define CTI_DT_CTM_ID		"arm,cti-ctm-id"
 
 /*
  * Find a registered coresight device from a device fwnode.
@@ -68,6 +78,12 @@ static const char *of_cti_get_node_name(const struct device_node *node)
 		return node->full_name;
 	return "unknown";
 }
+
+static bool of_cti_node_name_eq(const struct device_node *node,
+				const char *name)
+{
+	return of_node_name_eq(node, name);
+}
 #else
 static int of_cti_get_cpu_at_node(const struct device_node *node)
 {
@@ -78,6 +94,12 @@ static const char *of_cti_get_node_name(const struct device_node *node)
 {
 	return "unknown";
 }
+
+static bool of_cti_node_name_eq(const struct device_node *node,
+				const char *name)
+{
+	return false;
+}
 #endif
 
 static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
@@ -94,6 +116,14 @@ static const char *cti_plat_get_node_name(struct fwnode_handle *fwnode)
 	return "unknown";
 }
 
+static bool cti_plat_node_name_eq(struct fwnode_handle *fwnode,
+				  const char *name)
+{
+	if (is_of_node(fwnode))
+		return of_cti_node_name_eq(to_of_node(fwnode), name);
+	return false;
+}
+
 static int cti_plat_create_v8_etm_connection(struct device *dev,
 					     struct cti_drvdata *drvdata)
 {
@@ -205,6 +235,214 @@ static int cti_plat_create_v8_connections(struct device *dev,
 	return ret;
 }
 
+static int cti_plat_count_sig_elements(const struct fwnode_handle *fwnode,
+				       const char *name)
+{
+	int nr_elem = fwnode_property_count_u32(fwnode, name);
+
+	return (nr_elem < 0 ? 0 : nr_elem);
+}
+
+static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp,
+				    const struct fwnode_handle *fwnode,
+				    const char *grp_name)
+{
+	int idx, err = 0;
+	u32 *values;
+
+	if (!tgrp->nr_sigs)
+		return 0;
+
+	values = kcalloc(tgrp->nr_sigs, sizeof(u32), GFP_KERNEL);
+	if (!values)
+		return -ENOMEM;
+
+	err = fwnode_property_read_u32_array(fwnode, grp_name,
+					     values, tgrp->nr_sigs);
+
+	if (!err) {
+		/* set the signal usage mask */
+		for (idx = 0; idx < tgrp->nr_sigs; idx++)
+			tgrp->used_mask |= BIT(values[idx]);
+	}
+
+	kfree(values);
+	return err;
+}
+
+static int cti_plat_read_trig_types(struct cti_trig_grp *tgrp,
+				    const struct fwnode_handle *fwnode,
+				    const char *type_name)
+{
+	int items, used = 0, err = 0, nr_sigs;
+	u32 *values = NULL, i;
+
+	/* allocate an array according to number of signals in connection */
+	nr_sigs = tgrp->nr_sigs;
+	if (!nr_sigs)
+		return 0;
+
+	/* see if any types have been included in the device description */
+	items = cti_plat_count_sig_elements(fwnode, type_name);
+	if (items > nr_sigs)
+		return -EINVAL;
+
+	/* need an array to store the values iff there are any */
+	if (items) {
+		values = kcalloc(items, sizeof(u32), GFP_KERNEL);
+		if (!values)
+			return -ENOMEM;
+
+		err = fwnode_property_read_u32_array(fwnode, type_name,
+						     values, items);
+		if (err)
+			goto read_trig_types_out;
+	}
+
+	/*
+	 * Match type id to signal index, 1st type to 1st index etc.
+	 * If fewer types than signals default remainder to GEN_IO.
+	 */
+	for (i = 0; i < nr_sigs; i++) {
+		if (used < items) {
+			tgrp->sig_types[i] =
+				values[i] < CTI_TRIG_MAX ? values[i] : GEN_IO;
+			used++;
+		} else {
+			tgrp->sig_types[i] = GEN_IO;
+		}
+	}
+
+read_trig_types_out:
+	kfree(values);
+	return err;
+}
+
+static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata,
+					const struct fwnode_handle *fwnode)
+{
+	struct cti_trig_grp *tg = NULL;
+	int err = 0, nr_filter_sigs;
+
+	nr_filter_sigs = cti_plat_count_sig_elements(fwnode,
+						     CTI_DT_FILTER_OUT_SIGS);
+	if (nr_filter_sigs == 0)
+		return 0;
+
+	if (nr_filter_sigs > drvdata->config.nr_trig_max)
+		return -EINVAL;
+
+	tg = kzalloc(sizeof(*tg), GFP_KERNEL);
+	if (!tg)
+		return -ENOMEM;
+
+	err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS);
+	if (!err)
+		drvdata->config.trig_out_filter |= tg->used_mask;
+
+	kfree(tg);
+	return err;
+}
+
+static int cti_plat_create_connection(struct device *dev,
+				      struct cti_drvdata *drvdata,
+				      struct fwnode_handle *fwnode)
+{
+	struct cti_trig_con *tc = NULL;
+	int cpuid = -1, err = 0;
+	struct fwnode_handle *cs_fwnode = NULL;
+	struct coresight_device *csdev = NULL;
+	const char *assoc_name = "unknown";
+	char cpu_name_str[16];
+	int nr_sigs_in, nr_sigs_out;
+
+	/* look to see how many in and out signals we have */
+	nr_sigs_in = cti_plat_count_sig_elements(fwnode, CTI_DT_TRIGIN_SIGS);
+	nr_sigs_out = cti_plat_count_sig_elements(fwnode, CTI_DT_TRIGOUT_SIGS);
+
+	if ((nr_sigs_in > drvdata->config.nr_trig_max) ||
+	    (nr_sigs_out > drvdata->config.nr_trig_max))
+		return -EINVAL;
+
+	tc = cti_allocate_trig_con(dev, nr_sigs_in, nr_sigs_out);
+	if (!tc)
+		return -ENOMEM;
+
+	/* look for the signals properties. */
+	err = cti_plat_read_trig_group(tc->con_in, fwnode,
+				       CTI_DT_TRIGIN_SIGS);
+	if (err)
+		goto create_con_err;
+
+	err = cti_plat_read_trig_types(tc->con_in, fwnode,
+				       CTI_DT_TRIGIN_TYPES);
+	if (err)
+		goto create_con_err;
+
+	err = cti_plat_read_trig_group(tc->con_out, fwnode,
+				       CTI_DT_TRIGOUT_SIGS);
+	if (err)
+		goto create_con_err;
+
+	err = cti_plat_read_trig_types(tc->con_out, fwnode,
+				       CTI_DT_TRIGOUT_TYPES);
+	if (err)
+		goto create_con_err;
+
+	err = cti_plat_process_filter_sigs(drvdata, fwnode);
+	if (err)
+		goto create_con_err;
+
+	/* read the connection name if set - may be overridden by later */
+	fwnode_property_read_string(fwnode, CTI_DT_CONN_NAME, &assoc_name);
+
+	/* associated cpu ? */
+	cpuid = cti_plat_get_cpu_at_node(fwnode);
+	if (cpuid >= 0) {
+		drvdata->ctidev.cpu = cpuid;
+		scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid);
+		assoc_name = cpu_name_str;
+	} else {
+		/* associated device ? */
+		cs_fwnode = fwnode_find_reference(fwnode,
+						  CTI_DT_CSDEV_ASSOC, 0);
+		if (!IS_ERR_OR_NULL(cs_fwnode)) {
+			csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
+			if (csdev) /* use device name if csdev found */
+				assoc_name = dev_name(&csdev->dev);
+			else  /* otherwise node name for later association */
+				assoc_name = cti_plat_get_node_name(cs_fwnode);
+			fwnode_handle_put(cs_fwnode);
+		}
+	}
+	/* set up a connection */
+	err = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name);
+
+create_con_err:
+	return err;
+}
+
+static int cti_plat_create_impdef_connections(struct device *dev,
+					      struct cti_drvdata *drvdata)
+{
+	int rc = 0;
+	struct fwnode_handle *fwnode = dev_fwnode(dev);
+	struct fwnode_handle *child = NULL;
+
+	if (IS_ERR_OR_NULL(fwnode))
+		return -EINVAL;
+
+	fwnode_for_each_child_node(fwnode, child) {
+		if (cti_plat_node_name_eq(child, CTI_DT_CONNS))
+			rc = cti_plat_create_connection(dev, drvdata, child);
+		if (rc != 0)
+			break;
+	}
+	fwnode_handle_put(child);
+
+	return rc;
+}
+
 /* get the hardware configuration & connection data. */
 int cti_plat_get_hw_data(struct device *dev,
 			 struct cti_drvdata *drvdata)
@@ -212,12 +450,16 @@ int cti_plat_get_hw_data(struct device *dev,
 	int rc = 0;
 	struct cti_device *cti_dev = &drvdata->ctidev;
 
+	/* get any CTM ID - defaults to 0 */
+	device_property_read_u32(dev, CTI_DT_CTM_ID, &cti_dev->ctm_id);
+
 	/* check for a v8 architectural CTI device */
-	if (device_property_read_bool(dev, CTI_DT_V8ARCH)) {
+	if (device_property_read_bool(dev, CTI_DT_V8ARCH))
 		rc = cti_plat_create_v8_connections(dev, drvdata);
-		if (rc)
-			return rc;
-	}
+	else
+		rc = cti_plat_create_impdef_connections(dev, drvdata);
+	if (rc)
+		return rc;
 
 	/* if no connections, just add a single default based on max IN-OUT */
 	if (cti_dev->nr_trig_con == 0)
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 98de8a4768fc..f800402f73da 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -56,9 +56,20 @@ static ssize_t enable_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(enable);
 
+static ssize_t ctmid_show(struct device *dev,
+			  struct device_attribute *attr,
+			  char *buf)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", drvdata->ctidev.ctm_id);
+}
+static DEVICE_ATTR_RO(ctmid);
+
 /* attribute and group sysfs tables. */
 static struct attribute *coresight_cti_attrs[] = {
 	&dev_attr_enable.attr,
+	&dev_attr_ctmid.attr,
 	NULL,
 };
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices.
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (6 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-25 22:45   ` Mathieu Poirier
  2019-11-29 18:28   ` Suzuki Kuruppassery Poulose
  2019-11-19 23:19 ` [PATCH v5 09/14] coresight: cti: Add connection information to sysfs Mike Leach
                   ` (5 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

The CoreSight subsystem enables a path of devices from source to sink.
Any CTI devices associated with the path devices must be enabled at the
same time.

This patch adds an associated coresight_device element to the main
coresight device structure, and uses this to create associations between
the CTI and other devices based on the device tree data. The associated
device element is used to enable CTI in conjunction with the path elements.

CTI devices are reference counted so where a single CTI is associated with
multiple elements on the path, it will be enabled on the first associated
device enable, and disabled with the last associated device disable.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 drivers/hwtracing/coresight/coresight-cti.c   | 87 +++++++++++++++++++
 .../hwtracing/coresight/coresight-platform.c  | 23 +++++
 drivers/hwtracing/coresight/coresight-priv.h  |  6 ++
 drivers/hwtracing/coresight/coresight.c       | 58 +++++++++++--
 include/linux/coresight.h                     |  5 ++
 5 files changed, 173 insertions(+), 6 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
index 369488dd7b8e..cf116463149a 100644
--- a/drivers/hwtracing/coresight/coresight-cti.c
+++ b/drivers/hwtracing/coresight/coresight-cti.c
@@ -440,6 +440,90 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
 	return err;
 }
 
+/*
+ * Look for a matching connection device name in the list of
+ * connections. If found then swap in the csdev name and return
+ * found.
+ */
+static bool
+cti_match_con_name(struct cti_device *ctidev, const char *node_name,
+		   const char *csdev_name)
+{
+	struct cti_trig_con *trig_con;
+
+	list_for_each_entry(trig_con, &ctidev->trig_cons, node) {
+		if (trig_con->con_dev_name) {
+			if (!strcmp(node_name, trig_con->con_dev_name)) {
+				/* match: so swap in csdev name */
+				kfree(trig_con->con_dev_name);
+				trig_con->con_dev_name =
+					kstrdup(csdev_name, GFP_KERNEL);
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+/*
+ * Search the cti list to add an associated CTI into the supplied CS device
+ * This will set the association if CTI declared before the CS device
+ */
+void cti_add_assoc_to_csdev(struct coresight_device *csdev)
+{
+	struct cti_drvdata *ect_item;
+	struct cti_device *ctidev;
+	const char *node_name = NULL, *csdev_name;
+
+	/* protect the list */
+	mutex_lock(&ect_mutex);
+
+	/* exit if current is an ECT device.*/
+	if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net))
+		goto cti_add_done;
+
+	/* if we didn't find the csdev previously we used the fwnode name */
+	node_name = coresight_get_fwnode_name(csdev->dev.parent);
+
+	if (!node_name)
+		goto cti_add_done;
+
+	/* this is the name we want to use for the association */
+	csdev_name = dev_name(&csdev->dev);
+
+	/* for each CTI in list... */
+	list_for_each_entry(ect_item, &ect_net, node) {
+		ctidev = &ect_item->ctidev;
+		if (cti_match_con_name(ctidev, node_name, csdev_name)) {
+			/*
+			 * if we found a matching name then update the
+			 * association pointers.
+			 */
+			csdev->ect_dev = ect_item->csdev;
+			goto cti_add_done;
+		}
+	}
+cti_add_done:
+	mutex_unlock(&ect_mutex);
+}
+EXPORT_SYMBOL_GPL(cti_add_assoc_to_csdev);
+
+/*
+ * Update the cross references where the associated device was found
+ * while we were building the connection info. This will occur if the
+ * assoc device was registered before the CTI.
+ */
+static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)
+{
+	struct cti_trig_con *tc;
+	struct cti_device *ctidev = &drvdata->ctidev;
+
+	list_for_each_entry(tc, &ctidev->trig_cons, node) {
+		if (tc->con_dev)
+			tc->con_dev->ect_dev = drvdata->csdev;
+	}
+}
+
 /** cti ect operations **/
 int cti_enable(struct coresight_device *csdev)
 {
@@ -574,6 +658,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
 	drvdata->csdev_release = drvdata->csdev->dev.release;
 	drvdata->csdev->dev.release = cti_device_release;
 
+	/* set any cross references */
+	cti_update_conn_xrefs(drvdata);
+
 	/* all done - dec pm refcount */
 	pm_runtime_put(&adev->dev);
 	dev_info(&drvdata->csdev->dev, "CTI initialized\n");
diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
index 3c5bee429105..6721cb1af5fe 100644
--- a/drivers/hwtracing/coresight/coresight-platform.c
+++ b/drivers/hwtracing/coresight/coresight-platform.c
@@ -293,6 +293,12 @@ static int of_get_coresight_platform_data(struct device *dev,
 
 	return 0;
 }
+
+static inline const char *of_coresight_get_node_name(struct device *dev)
+{
+	return dev->of_node->full_name;
+}
+
 #else
 static inline int
 of_get_coresight_platform_data(struct device *dev,
@@ -305,6 +311,11 @@ static inline int of_coresight_get_cpu(struct device *dev)
 {
 	return -ENODEV;
 }
+
+static inline const char *of_coresight_get_node_name(struct device *dev)
+{
+	return NULL;
+}
 #endif
 
 #ifdef CONFIG_ACPI
@@ -766,6 +777,18 @@ static inline int acpi_coresight_get_cpu(struct device *dev)
 }
 #endif
 
+const char *coresight_get_fwnode_name(struct device *dev)
+{
+	const char *node_name = NULL;
+	struct fwnode_handle *fwnode = dev_fwnode(dev);
+
+	if (is_of_node(fwnode))
+		node_name = of_coresight_get_node_name(dev);
+
+	return node_name;
+}
+EXPORT_SYMBOL_GPL(coresight_get_fwnode_name);
+
 int coresight_get_cpu(struct device *dev)
 {
 	if (is_of_node(dev->fwnode))
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index aba6b789c969..484e5ec593bb 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -162,6 +162,12 @@ static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
 static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
 #endif
 
+#ifdef CONFIG_CORESIGHT_CTI
+extern void cti_add_assoc_to_csdev(struct coresight_device *csdev);
+#else
+static inline void cti_add_assoc_to_csdev(struct coresight_device *csdev) {}
+#endif
+
 /*
  * Macros and inline functions to handle CoreSight UCI data and driver
  * private data in AMBA ID table entries, and extract data values.
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 1a5fdf2710ff..7657be009246 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -216,6 +216,31 @@ void coresight_disclaim_device(void __iomem *base)
 	CS_LOCK(base);
 }
 
+/* enable or disable an associated CTI device of the supplied CS device */
+static int
+coresight_control_assoc_ectdev(struct coresight_device *csdev, bool enable)
+{
+	int ect_ret = 0;
+	struct coresight_device *ect_csdev = csdev->ect_dev;
+
+	if (!ect_csdev)
+		return 0;
+
+	if (enable) {
+		if (ect_ops(ect_csdev)->enable)
+			ect_ret = ect_ops(ect_csdev)->enable(ect_csdev);
+	} else {
+		if (ect_ops(ect_csdev)->disable)
+			ect_ret = ect_ops(ect_csdev)->disable(ect_csdev);
+	}
+
+	/* output warning if ECT enable is preventing trace operation */
+	if (ect_ret)
+		dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n",
+		 dev_name(&ect_csdev->dev), enable ? "enable" : "disable");
+	return ect_ret;
+}
+
 static int coresight_enable_sink(struct coresight_device *csdev,
 				 u32 mode, void *data)
 {
@@ -228,11 +253,15 @@ static int coresight_enable_sink(struct coresight_device *csdev,
 	if (!sink_ops(csdev)->enable)
 		return -EINVAL;
 
-	ret = sink_ops(csdev)->enable(csdev, mode, data);
+	ret = coresight_control_assoc_ectdev(csdev, true);
 	if (ret)
 		return ret;
+	ret = sink_ops(csdev)->enable(csdev, mode, data);
+	if (ret) {
+		coresight_control_assoc_ectdev(csdev, false);
+		return ret;
+	}
 	csdev->enable = true;
-
 	return 0;
 }
 
@@ -246,6 +275,7 @@ static void coresight_disable_sink(struct coresight_device *csdev)
 	ret = sink_ops(csdev)->disable(csdev);
 	if (ret)
 		return;
+	coresight_control_assoc_ectdev(csdev, false);
 	csdev->enable = false;
 }
 
@@ -269,8 +299,15 @@ static int coresight_enable_link(struct coresight_device *csdev,
 	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0)
 		return outport;
 
-	if (link_ops(csdev)->enable)
-		ret = link_ops(csdev)->enable(csdev, inport, outport);
+	if (link_ops(csdev)->enable) {
+		ret = coresight_control_assoc_ectdev(csdev, true);
+		if (!ret) {
+			ret = link_ops(csdev)->enable(csdev, inport, outport);
+			if (ret)
+				coresight_control_assoc_ectdev(csdev, false);
+		}
+	}
+
 	if (!ret)
 		csdev->enable = true;
 
@@ -300,8 +337,10 @@ static void coresight_disable_link(struct coresight_device *csdev,
 		nr_conns = 1;
 	}
 
-	if (link_ops(csdev)->disable)
+	if (link_ops(csdev)->disable) {
 		link_ops(csdev)->disable(csdev, inport, outport);
+		coresight_control_assoc_ectdev(csdev, false);
+	}
 
 	for (i = 0; i < nr_conns; i++)
 		if (atomic_read(&csdev->refcnt[i]) != 0)
@@ -322,9 +361,14 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
 
 	if (!csdev->enable) {
 		if (source_ops(csdev)->enable) {
-			ret = source_ops(csdev)->enable(csdev, NULL, mode);
+			ret = coresight_control_assoc_ectdev(csdev, true);
 			if (ret)
 				return ret;
+			ret = source_ops(csdev)->enable(csdev, NULL, mode);
+			if (ret) {
+				coresight_control_assoc_ectdev(csdev, false);
+				return ret;
+			};
 		}
 		csdev->enable = true;
 	}
@@ -347,6 +391,7 @@ static bool coresight_disable_source(struct coresight_device *csdev)
 	if (atomic_dec_return(csdev->refcnt) == 0) {
 		if (source_ops(csdev)->disable)
 			source_ops(csdev)->disable(csdev, NULL);
+		coresight_control_assoc_ectdev(csdev, false);
 		csdev->enable = false;
 	}
 	return !csdev->enable;
@@ -1252,6 +1297,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
 
 	coresight_fixup_device_conns(csdev);
 	coresight_fixup_orphan_conns(csdev);
+	cti_add_assoc_to_csdev(csdev);
 
 	mutex_unlock(&coresight_mutex);
 
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index b3e582d96a34..b5dc9baf0c58 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -163,6 +163,8 @@ struct coresight_connection {
  *		activated but not yet enabled.  Enabling for a _sink_
  *		appens when a source has been selected for that it.
  * @ea:		Device attribute for sink representation under PMU directory.
+ * @ect_dev:	Associated cross trigger device. Not part of the trace data
+ *		path or connections.
  */
 struct coresight_device {
 	struct coresight_platform_data *pdata;
@@ -176,6 +178,8 @@ struct coresight_device {
 	/* sink specific fields */
 	bool activated;	/* true only if a sink is part of a path */
 	struct dev_ext_attribute *ea;
+	/* cross trigger handling */
+	struct coresight_device *ect_dev;
 };
 
 /*
@@ -341,5 +345,6 @@ static inline bool coresight_loses_context_with_cpu(struct device *dev)
 extern int coresight_get_cpu(struct device *dev);
 
 struct coresight_platform_data *coresight_get_platform_data(struct device *dev);
+extern const char *coresight_get_fwnode_name(struct device *dev);
 
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 09/14] coresight: cti: Add connection information to sysfs
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (7 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-27 18:09   ` Mathieu Poirier
  2019-12-02  9:47   ` Suzuki Kuruppassery Poulose
  2019-11-19 23:19 ` [PATCH v5 10/14] dt-bindings: qcom: Add CTI options for qcom msm8916 Mike Leach
                   ` (4 subsequent siblings)
  13 siblings, 2 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Dynamically adds sysfs attributes for all connections defined in the CTI.

Each connection has a triggers<N> sub-directory with name, in_signals,
in_types, out_signals and out_types as read-only parameters in the
directory. in_ or out_ parameters may be omitted if there are no in or
out signals for the connection.

Additionally each device has a nr_cons in the connections sub-directory.

This allows clients to explore the connection and trigger signal details
without needing to refer to device tree or specification of the device.

Standardised type information is provided for certain common functions -
e.g. snk_full for a trigger from a sink indicating full. Otherwise type
defaults to genio.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../hwtracing/coresight/coresight-cti-sysfs.c | 376 +++++++++++++++++-
 drivers/hwtracing/coresight/coresight-cti.c   |  13 +-
 drivers/hwtracing/coresight/coresight-cti.h   |  11 +-
 3 files changed, 396 insertions(+), 4 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index f800402f73da..91986732506f 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -8,6 +8,67 @@
 
 #include "coresight-cti.h"
 
+/*
+ * Declare the number of static declared attribute groups
+ * Value includes groups + NULL value at end of table.
+ */
+#define CORESIGHT_CTI_STATIC_GROUPS_MAX 5
+
+/*
+ * List of trigger signal type names. Match the constants declared in
+ * include\dt-bindings\arm\coresight-cti-dt.h
+ */
+static const char * const sig_type_names[] = {
+	"genio",	/* GEN_IO */
+	"intreq",	/* GEN_INTREQ */
+	"intack",	/* GEN_INTACK */
+	"haltreq",	/* GEN_HALTREQ */
+	"restartreq",	/* GEN_RESTARTREQ */
+	"pe_edbgreq",	/* PE_EDBGREQ */
+	"pe_dbgrestart",/* PE_DBGRESTART */
+	"pe_ctiirq",	/* PE_CTIIRQ */
+	"pe_pmuirq",	/* PE_PMUIRQ */
+	"pe_dbgtrigger",/* PE_DBGTRIGGER */
+	"etm_extout",	/* ETM_EXTOUT */
+	"etm_extin",	/* ETM_EXTIN */
+	"snk_full",	/* SNK_FULL */
+	"snk_acqcomp",	/* SNK_ACQCOMP */
+	"snk_flushcomp",/* SNK_FLUSHCOMP */
+	"snk_flushin",	/* SNK_FLUSHIN */
+	"snk_trigin",	/* SNK_TRIGIN */
+	"stm_asyncout",	/* STM_ASYNCOUT */
+	"stm_tout_spte",/* STM_TOUT_SPTE */
+	"stm_tout_sw",	/* STM_TOUT_SW */
+	"stm_tout_hete",/* STM_TOUT_HETE */
+	"stm_hwevent",	/* STM_HWEVENT */
+	"ela_tstart",	/* ELA_TSTART */
+	"ela_tstop",	/* ELA_TSTOP */
+	"ela_dbgreq",	/* ELA_DBGREQ */
+};
+
+/* Show function pointer used in the connections dynamic declared attributes*/
+typedef ssize_t (*p_show_fn)(struct device *dev, struct device_attribute *attr,
+			     char *buf);
+
+/* Connection attribute types */
+enum cti_conn_attr_type {
+	CTI_CON_ATTR_NAME,
+	CTI_CON_ATTR_TRIGIN_SIG,
+	CTI_CON_ATTR_TRIGOUT_SIG,
+	CTI_CON_ATTR_TRIGIN_TYPES,
+	CTI_CON_ATTR_TRIGOUT_TYPES,
+	CTI_CON_ATTR_MAX,
+};
+
+/* Names for the connection attributes */
+static const char * const con_attr_names[CTI_CON_ATTR_MAX] = {
+	"name",
+	"in_signals",
+	"out_signals",
+	"in_types",
+	"out_types",
+};
+
 /* basic attributes */
 static ssize_t enable_show(struct device *dev,
 			   struct device_attribute *attr,
@@ -66,10 +127,21 @@ static ssize_t ctmid_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(ctmid);
 
+static ssize_t nr_trigger_cons_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", drvdata->ctidev.nr_trig_con);
+}
+static DEVICE_ATTR_RO(nr_trigger_cons);
+
 /* attribute and group sysfs tables. */
 static struct attribute *coresight_cti_attrs[] = {
 	&dev_attr_enable.attr,
 	&dev_attr_ctmid.attr,
+	&dev_attr_nr_trigger_cons.attr,
 	NULL,
 };
 
@@ -818,7 +890,306 @@ static struct attribute *coresight_cti_channel_attrs[] = {
 	NULL,
 };
 
-/* sysfs groups */
+/* Create the connections trigger groups and attrs dynamically */
+/*
+ * Each connection has dynamic group triggers<N> + name, trigin/out sigs/types
+ * attributes, + each device has static nr_trigger_cons giving the number
+ * of groups. e.g. in sysfs:-
+ * /cti_<name>/triggers0
+ * /cti_<name>/triggers1
+ * /cti_<name>/nr_trigger_cons
+ * where nr_trigger_cons = 2
+ */
+static ssize_t con_name_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	struct dev_ext_attribute *ext_attr =
+		container_of(attr, struct dev_ext_attribute, attr);
+	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n", con->con_dev_name);
+}
+
+static ssize_t trigin_sig_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct dev_ext_attribute *ext_attr =
+		container_of(attr, struct dev_ext_attribute, attr);
+	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *cfg = &drvdata->config;
+	unsigned long mask = con->con_in->used_mask;
+
+	return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
+}
+
+static ssize_t trigout_sig_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct dev_ext_attribute *ext_attr =
+		container_of(attr, struct dev_ext_attribute, attr);
+	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
+	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct cti_config *cfg = &drvdata->config;
+	unsigned long mask = con->con_out->used_mask;
+
+	return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
+}
+
+/* convert a sig type id to a name */
+static const char *
+cti_sig_type_name(struct cti_trig_con *con, int used_count, bool in)
+{
+	int idx = 0;
+	struct cti_trig_grp *grp = in ? con->con_in : con->con_out;
+
+	if (grp->sig_types) {
+		if (used_count < grp->nr_sigs)
+			idx = grp->sig_types[used_count];
+	}
+	return sig_type_names[idx];
+}
+
+static ssize_t trigin_type_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct dev_ext_attribute *ext_attr =
+		container_of(attr, struct dev_ext_attribute, attr);
+	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
+	int sig_idx, used = 0, b_sz = PAGE_SIZE;
+	const char *name;
+
+	for (sig_idx = 0; sig_idx < con->con_in->nr_sigs; sig_idx++) {
+		name = cti_sig_type_name(con, sig_idx, true);
+		used += scnprintf(buf + used, b_sz - used, "%s ", name);
+	}
+	used += scnprintf(buf + used, b_sz - used, "\n");
+	return used;
+}
+
+static ssize_t trigout_type_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct dev_ext_attribute *ext_attr =
+		container_of(attr, struct dev_ext_attribute, attr);
+	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
+	int sig_idx, used = 0, b_sz = PAGE_SIZE;
+	const char *name;
+
+	for (sig_idx = 0; sig_idx < con->con_out->nr_sigs; sig_idx++) {
+		name = cti_sig_type_name(con, sig_idx, false);
+		used += scnprintf(buf + used, b_sz - used, "%s ", name);
+	}
+	used += scnprintf(buf + used, b_sz - used, "\n");
+	return used;
+}
+
+/*
+ * Array of show function names declared above to allow selection
+ * for the connection attributes
+ */
+static p_show_fn show_fns[CTI_CON_ATTR_MAX] = {
+	con_name_show,
+	trigin_sig_show,
+	trigout_sig_show,
+	trigin_type_show,
+	trigout_type_show,
+};
+
+static int cti_create_con_sysfs_attr(struct cti_trig_con *con,
+				     enum cti_conn_attr_type attr_type,
+				     int attr_idx)
+{
+	struct dev_ext_attribute *dev_ext_attr = 0;
+	char *name = 0;
+
+	dev_ext_attr = kzalloc(sizeof(struct dev_ext_attribute), GFP_KERNEL);
+	if (dev_ext_attr) {
+		name = kstrdup(con_attr_names[attr_type], GFP_KERNEL);
+		if (name) {
+			/* fill out the underlying attribute struct */
+			dev_ext_attr->attr.attr.name = name;
+			dev_ext_attr->attr.attr.mode = 0444;
+
+			/* now the device_attribute struct */
+			dev_ext_attr->attr.show = show_fns[attr_type];
+		} else {
+			kfree(dev_ext_attr);
+			return -ENOMEM;
+		}
+	} else {
+		return -ENOMEM;
+	}
+	dev_ext_attr->var = con;
+	con->con_attrs[attr_idx] = &dev_ext_attr->attr.attr;
+	return 0;
+}
+
+static struct attribute_group *
+cti_create_con_sysfs_group(struct cti_device *ctidev, int con_idx,
+			   struct cti_trig_con *con)
+{
+	struct attribute_group *group = NULL;
+
+	group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
+	if (!group)
+		return NULL;
+
+	group->name = kasprintf(GFP_KERNEL, "triggers%d", con_idx);
+	if (!group->name) {
+		kfree(group);
+		return NULL;
+	}
+
+	ctidev->con_groups[con_idx + CORESIGHT_CTI_STATIC_GROUPS_MAX - 1]
+		= group;
+	con->attr_group = group;
+	return group;
+}
+
+/* create a triggers connection group and the attributes for that group */
+static int cti_create_con_attr_set(int con_idx, struct cti_device *ctidev,
+				   struct cti_trig_con *con)
+{
+	struct attribute_group *attr_group = NULL;
+	int attr_idx = 0;
+	int err = -ENOMEM;
+
+	attr_group = cti_create_con_sysfs_group(ctidev, con_idx, con);
+	if (!attr_group)
+		return -ENOMEM;
+
+	/* allocate NULL terminated array of attributes */
+	con->con_attrs = kcalloc(CTI_CON_ATTR_MAX + 1,
+				 sizeof(struct attribute *),
+				 GFP_KERNEL);
+	if (!con->con_attrs)
+		return -ENOMEM;
+
+	err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_NAME, attr_idx++);
+	if (err)
+		return err;
+
+	if (con->con_in->nr_sigs > 0) {
+		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_SIG,
+						attr_idx++);
+		if (err)
+			return err;
+
+		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_TYPES,
+						attr_idx++);
+		if (err)
+			return err;
+	}
+
+	if (con->con_in->nr_sigs > 0) {
+		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_SIG,
+						attr_idx++);
+		if (err)
+			return err;
+
+		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_TYPES,
+						attr_idx++);
+		if (err)
+			return err;
+	}
+	attr_group->attrs = con->con_attrs;
+	return 0;
+}
+
+/* create the array of group pointers for the CTI sysfs groups */
+int cti_create_cons_groups(struct cti_device *ctidev)
+{
+	int i, nr_groups;
+
+	/* nr groups - dynamic + static + NULL terminator */
+	nr_groups = ctidev->nr_trig_con + CORESIGHT_CTI_STATIC_GROUPS_MAX;
+	ctidev->con_groups = kcalloc(nr_groups,
+				     sizeof(struct attribute_group *),
+				     GFP_KERNEL);
+	if (!ctidev->con_groups)
+		return -ENOMEM;
+
+	/* populate first locations with the static set of groups */
+	for (i = 0; i < (CORESIGHT_CTI_STATIC_GROUPS_MAX - 1); i++)
+		ctidev->con_groups[i] = coresight_cti_groups[i];
+
+	return 0;
+}
+
+int cti_create_cons_sysfs(struct cti_drvdata *drvdata)
+{
+	struct cti_device *ctidev = &drvdata->ctidev;
+	int err, con_idx = 0;
+	struct cti_trig_con *tc = NULL;
+
+	err = cti_create_cons_groups(ctidev);
+	if (err)
+		return err;
+
+	/* add dynamic set for each connection */
+	list_for_each_entry(tc, &ctidev->trig_cons, node) {
+		err = cti_create_con_attr_set(con_idx++, ctidev, tc);
+		if (err)
+			goto cons_sysfs_err;
+	}
+	return 0;
+
+cons_sysfs_err:
+	cti_destroy_cons_sysfs(ctidev);
+	return err;
+}
+
+void cti_free_con_attr(struct attribute *con_attr)
+{
+	struct device_attribute *dattr =
+		container_of(con_attr, struct device_attribute, attr);
+	struct dev_ext_attribute *dev_ext_attr =
+		container_of(dattr, struct dev_ext_attribute, attr);
+	kfree(con_attr->name);
+	kfree(dev_ext_attr);
+}
+
+void cti_free_con_group(struct attribute_group *attr_group)
+{
+	if (attr_group) {
+		kfree(attr_group->name);
+		kfree(attr_group);
+	}
+}
+
+void cti_destroy_cons_attr_set(int con_idx, struct cti_device *ctidev,
+			       struct cti_trig_con *con)
+{
+	int i;
+
+	if (con->con_attrs) {
+		for (i = 0; i < CTI_CON_ATTR_MAX; i++) {
+			if (con->con_attrs[i])
+				cti_free_con_attr(con->con_attrs[i]);
+		}
+		kfree(con->con_attrs);
+	}
+	cti_free_con_group(con->attr_group);
+}
+
+void cti_destroy_cons_sysfs(struct cti_device *ctidev)
+{
+	struct cti_trig_con *tc;
+	int con_idx = 0;
+
+	list_for_each_entry(tc, &ctidev->trig_cons, node) {
+		cti_destroy_cons_attr_set(con_idx++, ctidev, tc);
+	}
+	kfree(ctidev->con_groups);
+}
+
+/* attribute and group sysfs tables. */
 static const struct attribute_group coresight_cti_group = {
 	.attrs = coresight_cti_attrs,
 };
@@ -838,7 +1209,8 @@ static const struct attribute_group coresight_cti_channels_group = {
 	.name = "channels",
 };
 
-const struct attribute_group *coresight_cti_groups[] = {
+const struct attribute_group *
+coresight_cti_groups[CORESIGHT_CTI_STATIC_GROUPS_MAX] = {
 	&coresight_cti_group,
 	&coresight_cti_mgmt_group,
 	&coresight_cti_regs_group,
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
index cf116463149a..c3d63cc53bdd 100644
--- a/drivers/hwtracing/coresight/coresight-cti.c
+++ b/drivers/hwtracing/coresight/coresight-cti.c
@@ -561,6 +561,9 @@ static void cti_device_release(struct device *dev)
 
 	mutex_lock(&ect_mutex);
 
+	/* clear the dynamic sysfs associate with connections */
+	cti_destroy_cons_sysfs(&drvdata->ctidev);
+
 	/* remove from the list */
 	list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
 		if (ect_item == drvdata) {
@@ -636,12 +639,20 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
 		goto err_out;
 	}
 
+	/* create dynamic attributes for connections */
+	ret = cti_create_cons_sysfs(drvdata);
+	if (ret) {
+		pr_err("%s: create dynamic sysfs entries failed\n",
+		       cti_desc.name);
+		goto err_out;
+	}
+
 	/* set up coresight component description */
 	cti_desc.pdata = pdata;
 	cti_desc.type = CORESIGHT_DEV_TYPE_ECT;
 	cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI;
 	cti_desc.ops = &cti_ops;
-	cti_desc.groups = coresight_cti_groups;
+	cti_desc.groups = drvdata->ctidev.con_groups;
 	cti_desc.dev = dev;
 	drvdata->csdev = coresight_register(&cti_desc);
 	if (IS_ERR(drvdata->csdev)) {
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index 9a22f6fcad65..dc5b265acf5e 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -74,6 +74,8 @@ struct cti_trig_grp {
  * @con_dev: coresight device connected to the CTI, NULL if not CS device
  * @con_dev_name: name of connected device (CS or CPU)
  * @node: entry node in list of connections.
+ * @con_attrs: Dynamic sysfs attributes specific to this connection.
+ * @attr_group: Dynamic attribute group created for this connection.
  */
 struct cti_trig_con {
 	struct cti_trig_grp *con_in;
@@ -81,6 +83,8 @@ struct cti_trig_con {
 	struct coresight_device *con_dev;
 	char *con_dev_name;
 	struct list_head node;
+	struct attribute **con_attrs;
+	struct attribute_group *attr_group;
 };
 
 /**
@@ -91,12 +95,15 @@ struct cti_trig_con {
  *          assumed there is a single CTM per SoC, ID 0).
  * @trig_cons: list of connections to this device.
  * @cpu: CPU ID if associated with CPU, -1 otherwise.
+ * @con_groups: combined static and dynamic sysfs groups for trigger
+ *		connections.
  */
 struct cti_device {
 	int nr_trig_con;
 	u32 ctm_id;
 	struct list_head trig_cons;
 	int cpu;
+	const struct attribute_group **con_groups;
 };
 
 /**
@@ -111,7 +118,7 @@ struct cti_device {
  * @trig_in_use: bitfield of in triggers registered as in use.
  * @trig_out_use: bitfield of out triggers registered as in use.
  * @trig_out_filter: bitfield of out triggers that are blocked if filter
- *	             enabled. Typically this would be dbgreq / restart on
+ *		     enabled. Typically this would be dbgreq / restart on
  *		     a core CTI.
  * @trig_filter_enable: 1 if filtering enabled.
  * @xtrig_rchan_sel: channel selection for xtrigger connection show.
@@ -214,6 +221,8 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
 			u32 channel_idx);
 int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
 		      u32 channel_idx);
+int cti_create_cons_sysfs(struct cti_drvdata *drvdata);
+void cti_destroy_cons_sysfs(struct cti_device *ctidev);
 struct coresight_platform_data *
 coresight_cti_get_platform_data(struct device *dev);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 10/14] dt-bindings: qcom: Add CTI options for qcom msm8916
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (8 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 09/14] coresight: cti: Add connection information to sysfs Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-27 18:18   ` Mathieu Poirier
  2019-11-19 23:19 ` [PATCH v5 11/14] dt-bindings: arm: Juno platform - add CTI entries to device tree Mike Leach
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Adds system and CPU bound CTI definitions for Qualcom msm8916 platform
(Dragonboard DB410C).
System CTIs 2-11 are omitted as no information available at present.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 arch/arm64/boot/dts/qcom/msm8916.dtsi | 85 +++++++++++++++++++++++++--
 1 file changed, 81 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 5ea9fb8f2f87..9589fc2cba22 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -8,6 +8,7 @@
 #include <dt-bindings/reset/qcom,gcc-msm8916.h>
 #include <dt-bindings/clock/qcom,rpmcc.h>
 #include <dt-bindings/thermal/thermal.h>
+#include <dt-bindings/arm/coresight-cti-dt.h>
 
 / {
 	interrupt-parent = <&intc>;
@@ -1357,7 +1358,7 @@
 			cpu = <&CPU3>;
 		};
 
-		etm@85c000 {
+		etm0: etm@85c000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x85c000 0x1000>;
 
@@ -1375,7 +1376,7 @@
 			};
 		};
 
-		etm@85d000 {
+		etm1: etm@85d000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x85d000 0x1000>;
 
@@ -1393,7 +1394,7 @@
 			};
 		};
 
-		etm@85e000 {
+		etm2: etm@85e000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x85e000 0x1000>;
 
@@ -1411,7 +1412,7 @@
 			};
 		};
 
-		etm@85f000 {
+		etm3: etm@85f000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x85f000 0x1000>;
 
@@ -1429,6 +1430,82 @@
 			};
 		};
 
+		/* System CTIs */
+		/* CTI 0 - TMC connections */
+		cti@810000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0x810000 0x1000>;
+
+			clocks = <&rpmcc RPM_QDSS_CLK>;
+			clock-names = "apb_pclk";
+		};
+
+		/* CTI 1 - TPIU connections */
+		cti@811000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0x811000 0x1000>;
+
+			clocks = <&rpmcc RPM_QDSS_CLK>;
+			clock-names = "apb_pclk";
+		};
+
+		/* CTIs 2-11 - no information - not instantiated */
+
+		/* Core CTIs; CTIs 12-15 */
+		/* CTI - CPU-0 */
+		cti@858000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0x858000 0x1000>;
+
+			clocks = <&rpmcc RPM_QDSS_CLK>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&CPU0>;
+			arm,cs-dev-assoc = <&etm0>;
+
+		};
+
+		/* CTI - CPU-1 */
+		cti@859000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0x859000 0x1000>;
+
+			clocks = <&rpmcc RPM_QDSS_CLK>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&CPU1>;
+			arm,cs-dev-assoc = <&etm1>;
+		};
+
+		/* CTI - CPU-2 */
+		cti@85a000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0x85a000 0x1000>;
+
+			clocks = <&rpmcc RPM_QDSS_CLK>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&CPU2>;
+			arm,cs-dev-assoc = <&etm2>;
+		};
+
+		/* CTI - CPU-3 */
+		cti@85b000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0x85b000 0x1000>;
+
+			clocks = <&rpmcc RPM_QDSS_CLK>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&CPU3>;
+			arm,cs-dev-assoc = <&etm3>;
+		};
+
+
 		venus: video-codec@1d00000 {
 			compatible = "qcom,msm8916-venus";
 			reg = <0x01d00000 0xff000>;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 11/14] dt-bindings: arm: Juno platform - add CTI entries to device tree.
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (9 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 10/14] dt-bindings: qcom: Add CTI options for qcom msm8916 Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-27 18:25   ` Mathieu Poirier
  2019-11-19 23:19 ` [PATCH v5 12/14] dt-bindings: hisilicon: Add CTI bindings for hi-6220 Mike Leach
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Add in CTI entries for Juno r0, r1 and r2 to device tree entries.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 arch/arm64/boot/dts/arm/juno-base.dtsi    | 150 +++++++++++++++++++++-
 arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi |  31 ++++-
 arch/arm64/boot/dts/arm/juno-r1.dts       |  25 ++++
 arch/arm64/boot/dts/arm/juno-r2.dts       |  25 ++++
 arch/arm64/boot/dts/arm/juno.dts          |  25 ++++
 5 files changed, 251 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi
index 26a039a028b8..4db2eca87dbf 100644
--- a/arch/arm64/boot/dts/arm/juno-base.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
@@ -108,7 +108,7 @@
 	 * The actual size is just 4K though 64K is reserved. Access to the
 	 * unmapped reserved region results in a DECERR response.
 	 */
-	etf@20010000 { /* etf0 */
+	etf_sys0: etf@20010000 { /* etf0 */
 		compatible = "arm,coresight-tmc", "arm,primecell";
 		reg = <0 0x20010000 0 0x1000>;
 
@@ -132,7 +132,7 @@
 		};
 	};
 
-	tpiu@20030000 {
+	tpiu_sys: tpiu@20030000 {
 		compatible = "arm,coresight-tpiu", "arm,primecell";
 		reg = <0 0x20030000 0 0x1000>;
 
@@ -185,7 +185,7 @@
 		};
 	};
 
-	etr@20070000 {
+	etr_sys: etr@20070000 {
 		compatible = "arm,coresight-tmc", "arm,primecell";
 		reg = <0 0x20070000 0 0x1000>;
 		iommus = <&smmu_etr 0>;
@@ -203,7 +203,7 @@
 		};
 	};
 
-	stm@20100000 {
+	stm_sys: stm@20100000 {
 		compatible = "arm,coresight-stm", "arm,primecell";
 		reg = <0 0x20100000 0 0x1000>,
 		      <0 0x28000000 0 0x1000000>;
@@ -280,6 +280,18 @@
 		};
 	};
 
+	cti0: cti@22020000 {
+		compatible = "arm,coresight-cti", "arm,primecell";
+		reg = <0 0x22020000 0 0x1000>;
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		power-domains = <&scpi_devpd 0>;
+
+		arm,cti-v8-arch;
+		arm,cs-dev-assoc = <&etm0>;
+	};
+
 	funnel@220c0000 { /* cluster0 funnel */
 		compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
 		reg = <0 0x220c0000 0 0x1000>;
@@ -340,6 +352,18 @@
 		};
 	};
 
+	cti1: cti@22120000 {
+		compatible = "arm,coresight-cti", "arm,primecell";
+		reg = <0 0x22120000 0 0x1000>;
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		power-domains = <&scpi_devpd 0>;
+
+		arm,cti-v8-arch;
+		arm,cs-dev-assoc = <&etm1>;
+	};
+
 	cpu_debug2: cpu-debug@23010000 {
 		compatible = "arm,coresight-cpu-debug", "arm,primecell";
 		reg = <0x0 0x23010000 0x0 0x1000>;
@@ -365,6 +389,18 @@
 		};
 	};
 
+	cti2: cti@23020000 {
+		compatible = "arm,coresight-cti", "arm,primecell";
+		reg = <0 0x23020000 0 0x1000>;
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		power-domains = <&scpi_devpd 0>;
+
+		arm,cti-v8-arch;
+		arm,cs-dev-assoc = <&etm2>;
+	};
+
 	funnel@230c0000 { /* cluster1 funnel */
 		compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
 		reg = <0 0x230c0000 0 0x1000>;
@@ -437,6 +473,18 @@
 		};
 	};
 
+	cti3: cti@23120000 {
+		compatible = "arm,coresight-cti", "arm,primecell";
+		reg = <0 0x23120000 0 0x1000>;
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		power-domains = <&scpi_devpd 0>;
+
+		arm,cti-v8-arch;
+		arm,cs-dev-assoc = <&etm3>;
+	};
+
 	cpu_debug4: cpu-debug@23210000 {
 		compatible = "arm,coresight-cpu-debug", "arm,primecell";
 		reg = <0x0 0x23210000 0x0 0x1000>;
@@ -462,6 +510,18 @@
 		};
 	};
 
+	cti4: cti@23220000 {
+		compatible = "arm,coresight-cti", "arm,primecell";
+		reg = <0 0x23220000 0 0x1000>;
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		power-domains = <&scpi_devpd 0>;
+
+		arm,cti-v8-arch;
+		arm,cs-dev-assoc = <&etm4>;
+	};
+
 	cpu_debug5: cpu-debug@23310000 {
 		compatible = "arm,coresight-cpu-debug", "arm,primecell";
 		reg = <0x0 0x23310000 0x0 0x1000>;
@@ -487,6 +547,88 @@
 		};
 	};
 
+	cti5: cti@23320000 {
+		compatible = "arm,coresight-cti", "arm,primecell";
+		reg = <0 0x23320000 0 0x1000>;
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		power-domains = <&scpi_devpd 0>;
+
+		arm,cti-v8-arch;
+		arm,cs-dev-assoc = <&etm5>;
+	};
+
+
+	cti@20020000 { /* sys_cti_0 */
+		compatible = "arm,coresight-cti", "arm,primecell";
+		reg = <0 0x20020000 0 0x1000>;
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		power-domains = <&scpi_devpd 0>;
+
+		trig-conns@0 {
+			arm,trig-in-sigs=<2 3>;
+			arm,trig-in-types=<SNK_FULL SNK_ACQCOMP>;
+			arm,trig-out-sigs=<0 1>;
+			arm,trig-out-types=<SNK_FLUSHIN SNK_TRIGIN>;
+			arm,cs-dev-assoc = <&etr_sys>;
+		};
+
+		trig-conns@1 {
+			arm,trig-in-sigs=<0 1>;
+			arm,trig-in-types=<SNK_FULL SNK_ACQCOMP>;
+			arm,trig-out-sigs=<7 6>;
+			arm,trig-out-types=<SNK_FLUSHIN SNK_TRIGIN>;
+			arm,cs-dev-assoc = <&etf_sys0>;
+		};
+
+		trig-conns@2 {
+			arm,trig-in-sigs=<4 5 6 7>;
+			arm,trig-in-types=<STM_TOUT_SPTE STM_TOUT_SW
+					   STM_TOUT_HETE STM_ASYNCOUT>;
+			arm,trig-out-sigs=<4 5>;
+			arm,trig-out-types=<STM_HWEVENT STM_HWEVENT>;
+			arm,cs-dev-assoc = <&stm_sys>;
+		};
+
+		trig-conns@3 {
+			arm,trig-out-sigs=<2 3>;
+			arm,trig-out-types=<SNK_FLUSHIN SNK_TRIGIN>;
+			arm,cs-dev-assoc = <&tpiu_sys>;
+		};
+	};
+
+	cti@20110000 { /* sys_cti_1 */
+		compatible = "arm,coresight-cti", "arm,primecell";
+		reg = <0 0x20110000 0 0x1000>;
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		power-domains = <&scpi_devpd 0>;
+
+		trig-conns@0 {
+			arm,trig-in-sigs=<0>;
+			arm,trig-in-types=<GEN_INTREQ>;
+			arm,trig-out-sigs=<0>;
+			arm,trig-out-types=<GEN_HALTREQ>;
+			arm,trig-conn-name = "sys_profiler";
+		};
+
+		trig-conns@1 {
+			arm,trig-out-sigs=<2 3>;
+			arm,trig-out-types=<GEN_HALTREQ GEN_RESTARTREQ>;
+			arm,trig-conn-name = "watchdog";
+		};
+
+		trig-conns@2 {
+			arm,trig-out-sigs=<1 6>;
+			arm,trig-out-types=<GEN_HALTREQ GEN_RESTARTREQ>;
+			arm,trig-conn-name = "g_counter";
+		};
+	};
+
 	sram: sram@2e000000 {
 		compatible = "arm,juno-sram-ns", "mmio-sram";
 		reg = <0x0 0x2e000000 0x0 0x8000>;
diff --git a/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi b/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi
index eda3d9e18af6..308f4eee8b29 100644
--- a/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi
@@ -23,7 +23,7 @@
 		};
 	};
 
-	etf@20140000 { /* etf1 */
+	etf_sys1: etf@20140000 { /* etf1 */
 		compatible = "arm,coresight-tmc", "arm,primecell";
 		reg = <0 0x20140000 0 0x1000>;
 
@@ -82,4 +82,33 @@
 
 		};
 	};
+
+	cti@20160000 { /* sys_cti_2 */
+		compatible = "arm,coresight-cti", "arm,primecell";
+		reg = <0 0x20160000 0 0x1000>;
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		power-domains = <&scpi_devpd 0>;
+
+		trig-conns@0 {
+			arm,trig-in-sigs=<0 1>;
+			arm,trig-in-types=<SNK_FULL SNK_ACQCOMP>;
+			arm,trig-out-sigs=<0 1>;
+			arm,trig-out-types=<SNK_FLUSHIN SNK_TRIGIN>;
+			arm,cs-dev-assoc = <&etf_sys1>;
+		};
+
+		trig-conns@1 {
+			arm,trig-in-sigs=<2 3 4>;
+			arm,trig-in-types=<ELA_DBGREQ ELA_TSTART ELA_TSTOP>;
+			arm,trig-conn-name = "ela_clus_0";
+		};
+
+		trig-conns@2 {
+			arm,trig-in-sigs=<5 6 7>;
+			arm,trig-in-types=<ELA_DBGREQ ELA_TSTART ELA_TSTOP>;
+			arm,trig-conn-name = "ela_clus_1";
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts
index 5f290090b0cf..02aa51eb311d 100644
--- a/arch/arm64/boot/dts/arm/juno-r1.dts
+++ b/arch/arm64/boot/dts/arm/juno-r1.dts
@@ -9,6 +9,7 @@
 /dts-v1/;
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/arm/coresight-cti-dt.h>
 #include "juno-base.dtsi"
 #include "juno-cs-r1r2.dtsi"
 
@@ -309,3 +310,27 @@
 &cpu_debug5 {
 	cpu = <&A53_3>;
 };
+
+&cti0 {
+	cpu = <&A57_0>;
+};
+
+&cti1 {
+	cpu = <&A57_1>;
+};
+
+&cti2 {
+	cpu = <&A53_0>;
+};
+
+&cti3 {
+	cpu = <&A53_1>;
+};
+
+&cti4 {
+	cpu = <&A53_2>;
+};
+
+&cti5 {
+	cpu = <&A53_3>;
+};
diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts b/arch/arm64/boot/dts/arm/juno-r2.dts
index 305300dd521c..75bb27c2d4dc 100644
--- a/arch/arm64/boot/dts/arm/juno-r2.dts
+++ b/arch/arm64/boot/dts/arm/juno-r2.dts
@@ -9,6 +9,7 @@
 /dts-v1/;
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/arm/coresight-cti-dt.h>
 #include "juno-base.dtsi"
 #include "juno-cs-r1r2.dtsi"
 
@@ -315,3 +316,27 @@
 &cpu_debug5 {
 	cpu = <&A53_3>;
 };
+
+&cti0 {
+	cpu = <&A72_0>;
+};
+
+&cti1 {
+	cpu = <&A72_1>;
+};
+
+&cti2 {
+	cpu = <&A53_0>;
+};
+
+&cti3 {
+	cpu = <&A53_1>;
+};
+
+&cti4 {
+	cpu = <&A53_2>;
+};
+
+&cti5 {
+	cpu = <&A53_3>;
+};
diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
index f00cffbd032c..dbc22e70b62c 100644
--- a/arch/arm64/boot/dts/arm/juno.dts
+++ b/arch/arm64/boot/dts/arm/juno.dts
@@ -9,6 +9,7 @@
 /dts-v1/;
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/arm/coresight-cti-dt.h>
 #include "juno-base.dtsi"
 
 / {
@@ -295,3 +296,27 @@
 &cpu_debug5 {
 	cpu = <&A53_3>;
 };
+
+&cti0 {
+	cpu = <&A57_0>;
+};
+
+&cti1 {
+	cpu = <&A57_1>;
+};
+
+&cti2 {
+	cpu = <&A53_0>;
+};
+
+&cti3 {
+	cpu = <&A53_1>;
+};
+
+&cti4 {
+	cpu = <&A53_2>;
+};
+
+&cti5 {
+	cpu = <&A53_3>;
+};
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 12/14] dt-bindings: hisilicon: Add CTI bindings for hi-6220
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (10 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 11/14] dt-bindings: arm: Juno platform - add CTI entries to device tree Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-19 23:19 ` [PATCH v5 13/14] docs: coresight: Update documentation for CoreSight to cover CTI Mike Leach
  2019-11-19 23:19 ` [PATCH v5 14/14] docs: sysfs: coresight: Add sysfs ABI documentation for CTI Mike Leach
  13 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Adds in CTI device tree information for the Hikey620 board.

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Tested-by: Leo Yan <leo.yan@linaro.org>
Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../boot/dts/hisilicon/hi6220-coresight.dtsi  | 130 ++++++++++++++++--
 1 file changed, 122 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi
index 651771a73ed6..806f0526f18f 100644
--- a/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi6220-coresight.dtsi
@@ -213,7 +213,7 @@
 			};
 		};
 
-		etm@f659c000 {
+		etm0: etm@f659c000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0 0xf659c000 0 0x1000>;
 
@@ -232,7 +232,7 @@
 			};
 		};
 
-		etm@f659d000 {
+		etm1: etm@f659d000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0 0xf659d000 0 0x1000>;
 
@@ -251,7 +251,7 @@
 			};
 		};
 
-		etm@f659e000 {
+		etm2: etm@f659e000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0 0xf659e000 0 0x1000>;
 
@@ -270,7 +270,7 @@
 			};
 		};
 
-		etm@f659f000 {
+		etm3: etm@f659f000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0 0xf659f000 0 0x1000>;
 
@@ -289,7 +289,7 @@
 			};
 		};
 
-		etm@f65dc000 {
+		etm4: etm@f65dc000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0 0xf65dc000 0 0x1000>;
 
@@ -308,7 +308,7 @@
 			};
 		};
 
-		etm@f65dd000 {
+		etm5: etm@f65dd000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0 0xf65dd000 0 0x1000>;
 
@@ -327,7 +327,7 @@
 			};
 		};
 
-		etm@f65de000 {
+		etm6: etm@f65de000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0 0xf65de000 0 0x1000>;
 
@@ -346,7 +346,7 @@
 			};
 		};
 
-		etm@f65df000 {
+		etm7: etm@f65df000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0 0xf65df000 0 0x1000>;
 
@@ -364,5 +364,119 @@
 				};
 			};
 		};
+
+		/* System CTIs */
+		/* CTI 0 - TMC and TPIU connections */
+		cti@f6403000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0 0xf6403000 0 0x1000>;
+
+			clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>;
+			clock-names = "apb_pclk";
+		};
+
+		/* CTI - CPU-0 */
+		cti@f6598000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0 0xf6598000 0 0x1000>;
+
+			clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&cpu0>;
+			arm,cs-dev-assoc = <&etm0>;
+		};
+
+		/* CTI - CPU-1 */
+		cti@f6599000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0 0xf6599000 0 0x1000>;
+
+			clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&cpu1>;
+			arm,cs-dev-assoc = <&etm1>;
+		};
+
+		/* CTI - CPU-2 */
+		cti@f659a000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0 0xf659a000 0 0x1000>;
+
+			clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&cpu2>;
+			arm,cs-dev-assoc = <&etm2>;
+		};
+
+		/* CTI - CPU-3 */
+		cti@f659b000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0 0xf659b000 0 0x1000>;
+
+			clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&cpu3>;
+			arm,cs-dev-assoc = <&etm3>;
+		};
+
+		/* CTI - CPU-4 */
+		cti@f65d8000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0 0xf65d8000 0 0x1000>;
+
+			clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&cpu4>;
+			arm,cs-dev-assoc = <&etm4>;
+		};
+
+		/* CTI - CPU-5 */
+		cti@f65d9000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0 0xf65d9000 0 0x1000>;
+
+			clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&cpu5>;
+			arm,cs-dev-assoc = <&etm5>;
+		};
+
+		/* CTI - CPU-6 */
+		cti@f65da000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0 0xf65da000 0 0x1000>;
+
+			clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&cpu6>;
+			arm,cs-dev-assoc = <&etm6>;
+		};
+
+		/* CTI - CPU-7 */
+		cti@f65db000 {
+			compatible = "arm,coresight-cti", "arm,primecell";
+			reg = <0 0xf65db000 0 0x1000>;
+
+			clocks = <&acpu_sctrl HI6220_ACPU_SFT_AT_S>;
+			clock-names = "apb_pclk";
+
+			arm,cti-v8-arch;
+			cpu = <&cpu7>;
+			arm,cs-dev-assoc = <&etm7>;
+		};
 	};
 };
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 13/14] docs: coresight: Update documentation for CoreSight to cover CTI.
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (11 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 12/14] dt-bindings: hisilicon: Add CTI bindings for hi-6220 Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-27 19:00   ` Mathieu Poirier
  2019-12-02 10:43   ` Suzuki Kuruppassery Poulose
  2019-11-19 23:19 ` [PATCH v5 14/14] docs: sysfs: coresight: Add sysfs ABI documentation for CTI Mike Leach
  13 siblings, 2 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Add new document covering CTI / CTM usage in CoreSight.

Add section in coresight.rst introducing CTI and CTM modules with link
to new document.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../trace/coresight/coresight-ect.rst         | 200 ++++++++++++++++++
 Documentation/trace/coresight/coresight.rst   |  13 ++
 2 files changed, 213 insertions(+)
 create mode 100644 Documentation/trace/coresight/coresight-ect.rst

diff --git a/Documentation/trace/coresight/coresight-ect.rst b/Documentation/trace/coresight/coresight-ect.rst
new file mode 100644
index 000000000000..6448cf910f20
--- /dev/null
+++ b/Documentation/trace/coresight/coresight-ect.rst
@@ -0,0 +1,200 @@
+=============================================
+CoreSight Embedded Cross Trigger (CTI & CTM).
+=============================================
+
+    :Author:   Mike Leach <mike.leach@linaro.org>
+    :Date:     November 2019
+
+Hardware Description
+--------------------
+
+The CoreSight Cross Trigger Interface (CTI) is a hardware device that takes
+individual input and output hardware signals known as triggers to and from
+devices and interconnects them via the Cross Trigger Matrix (CTM) to other
+devices via numbered channels, in order to propagate events between devices.
+
+e.g.::
+
+ 0000000  in_trigs  :::::::
+ 0 C   0----------->:     :             +======>(other CTI channel IO)
+ 0  P  0<-----------:     :             v
+ 0   U 0  out_trigs :     : Channels  *****      :::::::
+ 0000000            : CTI :<=========>*CTM*<====>: CTI :---+
+ #######  in_trigs  :     : (id 0-3)  *****      :::::::   v
+ # ETM #----------->:     :                         ^   #######
+ #     #<-----------:     :                         +---# ETR #
+ ####### out_trigs  :::::::                             #######
+
+The CTI driver enables the programming of the CTI to attach triggers to
+channels. When an input trigger becomes active, the attached channel will
+become active. Any output trigger attached to that channel will also
+become active. The active channel is propagated to other CTIs via the CTM,
+activiating connected output triggers there, unless filtered by the CTI
+channel gate.
+
+It is also possible to activate a channel using system software directly
+programming registers in the CTI.
+
+The CTIs are registered by the system to be associated with CPUs and/or other
+CoreSight devices on the trace data path. When these devices are enabled the
+attached CTIs will also be enabled. By default/on power up the CTIs have
+no programmed trigger/channel attachments, so will not affect the system
+until explicitly programmed.
+
+The hardware trigger connections between CTIs and devices is implementation
+defined, unless the CPU/ETM combination is a v8 architecture, in which case
+the connections have an architecturally defined standard layout.
+
+The hardware trigger signals can also be connected to non-CoreSight devices
+(e.g. UART), or be propagated off chip as hardware IO lines.
+
+All the CTI devices are associated with a CTM. On many systems there will be a
+single effective CTM (one CTM, or multiple CTMs all interconnected), but it is
+possible that systems can have nets of CTIs+CTM that are not interconnected by
+a CTM to each other. On these systems a CTM index is declared to associate
+CTI devices that are interconnected via a given CTM.
+
+Sysfs files and directories
+---------------------------
+
+The CTI devices appear on the existing CoreSight bus alongside the other
+CoreSight devices::
+
+    >$ ls /sys/bus/coresight/devices
+     cti_cpu0  cti_cpu2  cti_sys0  etm0  etm2  funnel0  replicator0  tmc_etr0
+     cti_cpu1  cti_cpu3  cti_sys1  etm1  etm3  funnel1  tmc_etf0     tpiu0
+
+The ``cti_cpu<N>`` named CTIs are associated with a CPU, and any ETM used by
+that core. the ``cti_sys<N>`` CTIs are general system infrastructure CTIs that
+can be associated with other CoreSight devices, or other system hardware
+capable of generating or using trigger signals.::
+
+  >$ ls /sys/bus/coresight/devices/etm0/cti_cpu0
+  channels  ctmid  enable  nr_trigger_cons mgmt  power  regs  subsystem
+  triggers0 triggers1  uevent
+
+*Key file items are:-*
+   * ``enable``: enables/disables the CTI.
+   * ``ctmid`` : associated CTM - only relevant if system has multiple CTI+CTM
+     clusters that are not interconnected.
+   * ``nr_trigger_cons`` : total connections - triggers<N> directories.
+
+*Sub-directories:-*
+   * ``triggers<N>``: contains list of triggers for an individual connection.
+   * ``channels``: Contains the channel API - CTI main programming interface.
+   * ``regs``: Gives access to the raw programmable CTI regs.
+   * ``mgmt``: the standard CoreSight management registers.
+
+
+triggers<N> directories
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Individual trigger connection information. This describes trigger signals for
+CoreSight and non-CoreSight connections.
+
+Each triggers directory has a set of parameters describing the triggers for
+the connection.
+
+   * ``name`` : name of connection
+   * ``in_signals`` : input trigger signal indexes used in this connection.
+   * ``in_types`` : functional types for in signals.
+   * ``out_signals`` : output trigger signals for this connection.
+   * ``out_types`` : functional types for out signals.
+
+e.g::
+
+    >$ ls ./cti_cpu0/triggers0/
+    in_signals  in_types  name  out_signals  out_types
+    >$ cat ./cti_cpu0/triggers0/name
+    cpu0
+    >$ cat ./cti_cpu0/triggers0/out_signals
+    0-2
+    >$ cat ./cti_cpu0/triggers0/out_types
+    pe_edbgreq pe_dbgrestart pe_ctiirq
+    >$ cat ./cti_cpu0/triggers0/in_signals
+    0-1
+    >$ cat ./cti_cpu0/triggers0/in_types
+    pe_dbgtrigger pe_pmuirq
+
+If a connection has zero signals in either the 'in' or 'out' triggers then
+those parameters will be omitted.
+
+Channels API Directory
+~~~~~~~~~~~~~~~~~~~~~~
+
+This provides an easy way to attach triggers to channels, without needing
+the multiple register operations that are required if manipluating the
+'regs' sub-dir elements directly.
+
+A number of files provide this API::
+
+   >$ ls ./cti_sys0/channels/
+   chan_clear         chan_inuse         chan_xtrigs_view      trigin_detach
+   chan_free          chan_pulse         chan_xtrigs_view_sel  trigout_attach
+   chan_gate_disable  chan_set           trig_filter_enable    trigout_detach
+   chan_gate_enable   chan_xtrigs_reset  trigin_attach         trigout_filtered
+
+Most access to these elements take the form::
+
+  echo <chan> [<trigger>] > /<device_path>/<operation>
+
+where the optional <trigger> is only needed for trigXX_attach | detach
+operations.
+
+e.g.::
+
+   >$ echo 0 1 > ./cti_sys0/channels/trigout_attach
+   >$ echo 0 > ./cti_sys0/channels/chan_set
+
+Attaches trigout(1) to channel(0), then activates channel(0) generating a
+set state on cti_sys0.trigout(1)
+
+
+*API operations*
+
+   * ``trigin_attach, trigout_attach``: Attach a channel to a trigger signal.
+   * ``trigin_detach, trigout_detach``: Detach a channel from a trigger signal.
+   * ``chan_set``: Set the channel - the set state will be propogated around
+     the CTM to other connected devices.
+   * ``chan_clear``: Clear the channel.
+   * ``chan_pulse``: Set the channel for a single CoreSight clock cycle.
+   * ``chan_gate_enable``: Write operation sets the CTI gate to propagate
+     (enable) the channel to other devices. This operation takes a channel
+     number. CTI gate is enabled for all channels by default at power up. Read
+     to list the currently enabled channels on the gate.
+   * ``chan_gate_disable``: Write channel number to disable gate for that
+     channel.
+   * ``chan_inuse``: Show the current channels attached to any signal
+   * ``chan_free``: Show channels with no attached signals.
+   * ``chan_xtrig_view``: write a channel number to select a channel to view,
+     read to show the cross triggers programmed for the selected channel.
+   * ``trig_filter_enable``: Defaults to enabled, disable to allow potentially
+     dangerous output signals to be set.
+   * ``trigout_filtered``: Trigger out signals that are prevented from being
+     set if filtering ``trig_filter_enable`` is enabled. One use is to prevent
+     accidental ``EDBGREQ`` signals stopping a core.
+   * ``chan_xtrigs_reset``: Write 1 to clear all channel / trigger programming.
+     Resets device hardware to default state.
+
+e.g.::
+
+   .../cti_sys0/channels# echo 2 1 > trigin_attach
+   .../cti_sys0/channels# echo 2 6 > trigout_attach
+   .../cti_sys0/channels# cat chan_free
+   0-1,3
+   .../cti_sys0/channels# cat chan_inuse
+   2
+   .../cti_sys0/channels# echo 2 > chan_xtrigs_view
+   .../cti_sys0/channels# cat chan_xtrigs_view
+   [2] IN: 1 OUT: 6
+   .../cti_sys0/# echo 1 > enable
+   .../cti_sys0/channels# echo 2 > chan_set
+   .../cti_sys0/channels# cat ../regs/choutstatus
+   0x4
+   .../cti_sys0/channels# cat ../regs/trigoutstatus
+   0x40
+   .../cti_sys0/channels# echo 2 > chan_clear
+   .../cti_sys0/channels# cat ../regs/trigoutstatus
+   0x0
+   .../cti_sys0/channels# cat ../regs/trigoutstatus
+   0x0
diff --git a/Documentation/trace/coresight/coresight.rst b/Documentation/trace/coresight/coresight.rst
index a566719f8e7e..108600ee1e12 100644
--- a/Documentation/trace/coresight/coresight.rst
+++ b/Documentation/trace/coresight/coresight.rst
@@ -491,8 +491,21 @@ interface provided for that purpose by the generic STM API::
 
 Details on how to use the generic STM API can be found here:- :doc:`../stm` [#second]_.
 
+The CTI & CTM Modules
+---------------------
+
+The CTI (Cross Trigger Interface) provides a set of trigger signals between
+individual CTIs and components, and can propagate these between all CTIs via
+channels on the CTM (Cross Trigger Matrix).
+
+A separate documentation file is provided to explain the use of these devices.
+(:doc:`coresight-ect`) [#fourth]_.
+
+
 .. [#first] Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
 
 .. [#second] Documentation/trace/stm.rst
 
 .. [#third] https://github.com/Linaro/perf-opencsd
+
+.. [#fourth] Documentation/trace/coresight/coresight-ect.rst
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* [PATCH v5 14/14] docs: sysfs: coresight: Add sysfs ABI documentation for CTI
  2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
                   ` (12 preceding siblings ...)
  2019-11-19 23:19 ` [PATCH v5 13/14] docs: coresight: Update documentation for CoreSight to cover CTI Mike Leach
@ 2019-11-19 23:19 ` Mike Leach
  2019-11-27 19:08   ` Mathieu Poirier
  13 siblings, 1 reply; 62+ messages in thread
From: Mike Leach @ 2019-11-19 23:19 UTC (permalink / raw)
  To: mike.leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier, suzuki.poulose

Add API usage document for sysfs API in CTI driver.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../testing/sysfs-bus-coresight-devices-cti   | 221 ++++++++++++++++++
 1 file changed, 221 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-cti

diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
new file mode 100644
index 000000000000..d867800f567f
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
@@ -0,0 +1,221 @@
+What:		/sys/bus/coresight/devices/<cti-name>/enable
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Enable/Disable the CTI hardware.
+
+What:		/sys/bus/coresight/devices/<cti-name>/ctmid
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) Display the associated CTM ID
+
+What:		/sys/bus/coresight/devices/<cti-name>/nr_trigger_cons
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) Number of devices connected to triggers on this CTI
+
+What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/name
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) Name of connected device <N>
+
+What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/in_signals
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) Input trigger signals from connected device <N>
+
+What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/in_types
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) Functional types for the input trigger signals
+		from connected device <N>
+
+What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/out_signals
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) Output trigger signals to connected device <N>
+
+What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/out_types
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) Functional types for the output trigger signals
+		to connected device <N>
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/inout_sel
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Select the index for inen and outen registers.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/inen
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Read or write the CTIINEN register selected by inout_sel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/outen
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Read or write the CTIOUTEN register selected by inout_sel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/gate
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Read or write CTIGATE register.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/asicctl
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Read or write ASICCTL register.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/intack
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Write the INTACK register.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/appset
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Set CTIAPPSET register to activate channel. Read back to
+		determine current value of register.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/appclear
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Write APPCLEAR register to deactivate channel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/apppulse
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Write APPPULSE to pulse a channel active for one clock
+		cycle.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/chinstatus
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) Read current status of channel inputs.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/choutstatus
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) read current status of channel outputs.
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/triginstatus
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) read current status of input trigger signals
+
+What:		/sys/bus/coresight/devices/<cti-name>/regs/trigoutstatus
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) read current status of output trigger signals.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/trigin_attach
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Attach a CTI input trigger to a CTM channel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/trigin_detach
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Detach a CTI input trigger from a CTM channel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/trigout_attach
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Attach a CTI output trigger to a CTM channel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/trigout_detach
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Detach a CTI output trigger from a CTM channel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_gate_enable
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Enable CTIGATE for single channel (W) or list enabled
+		channels through the gate (R).
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_gate_disable
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Disable CTIGATE for single channel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_set
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Activate a single channel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_clear
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Deactivate a single channel.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_pulse
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Pulse a single channel - activate for a single clock cycle.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/trigout_filtered
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) List of output triggers filtered across all connections.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/trig_filter_enable
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Enable or disable trigger output signal filtering.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_inuse
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) show channels with at least one attached trigger signal.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_free
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(R) show channels with no attached trigger signals.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_view
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(RW) Write channel number to select a channel to view, read to
+		see triggers attached to selected channel on this CTI.
+
+What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_reset
+Date:		Jul 2019
+KernelVersion	5.4
+Contact:	Mike Leach or Mathieu Poirier
+Description:	(W) Clear all channel / trigger programming.
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions.
  2019-11-19 23:19 ` [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions Mike Leach
@ 2019-11-20 19:06   ` Mathieu Poirier
  2019-11-20 22:39     ` Mike Leach
  2019-11-22 23:33   ` Rob Herring
  2019-11-28 18:38   ` Suzuki Kuruppassery Poulose
  2 siblings, 1 reply; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-20 19:06 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:03PM +0000, Mike Leach wrote:
> Adds new coresight-cti.yaml file describing the bindings required to define
> CTI in the device trees.
> 
> Adds an include file to dt-bindings/arm to define constants describing
> common signal functionality used in CoreSight and generic usage.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  .../bindings/arm/coresight-cti.yaml           | 303 ++++++++++++++++++
>  .../devicetree/bindings/arm/coresight.txt     |   7 +
>  MAINTAINERS                                   |   2 +
>  include/dt-bindings/arm/coresight-cti-dt.h    |  37 +++
>  4 files changed, 349 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/coresight-cti.yaml
>  create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h
> 
> diff --git a/Documentation/devicetree/bindings/arm/coresight-cti.yaml b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> new file mode 100644
> index 000000000000..882c72f1c798
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> @@ -0,0 +1,303 @@
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright 2019 Linaro Ltd.
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/coresight-cti.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: ARM Coresight Cross Trigger Interface (CTI) device.
> +
> +description: |
> +  The CoreSight Embedded Cross Trigger (ECT) consists of CTI devices connected
> +  to one or more CoreSight components and/or a CPU, with CTIs interconnected in
> +  a star topology via the CTM (which is not programmable). The ECT components
> +  are not part of the trace generation data path and are thus not part of the
> +  CoreSight graph described in the general CoreSight bindings file
> +  coresight.txt.
> +
> +  The CTI component properties define the connections between the individual
> +  CTI and the components it is directly connected to, consisting of input and
> +  output hardware trigger signals. CTIs can have a maximum number of input and
> +  output hardware trigger signals (8 each for v1 CTI, 32 each for v2 CTI). The
> +  number is defined at design time, the maximum of each defined in the DEVID
> +  register.
> +
> +  CTIs are interconnected in a star topology via the CTM, using a number of
> +  programmable channels usually 4, but again implementation defined and
> +  described in the DEVID register. The star topology is not required to be
> +  described in the bindings as the actual connections are software
> +  programmable.
> +
> +  In general the connections between CTI and components via the trigger signals
> +  are implementation defined, other than when v8 core and ETM is present.
> +  The v8 architecture defines the required signal connections between CPU core
> +  and CTI, and ETM and CTI, if the ETM if present.
> +
> +  When only minimal information is available for the CTI trigger connections,
> +  then a minimal driver binding can be declare with no explicit trigger
> +  signals. This will result in the using the DEVID register to set the
> +  input and output triggers and channels in use. Any user / client
> +  application will require additional information on the connections
> +  between the CTI and other components for correct operation. This minimal
> +  binding may be used when using the Integration Control registers to
> +  discover connections between CTI and other CoreSight components,
> +
> +  Certain triggers between CoreSight devices and the CTI have specific types
> +  and usages. These can be defined along with the signal indexes with the
> +  constants defined in <dt-bindings/arm/coresight-cti-dt.h>
> +
> +  For example a CTI connected to a core will usually have a DBGREQ signal. This
> +  is defined in the binding as type PE_EDBGREQ. These types will appear in an
> +  optional array alongside the signal indexes. Omitting types will default all
> +  signals to GEN_IO.
> +
> +  Note that some hardware trigger signals can be connected to non-CoreSight
> +  components (e.g. UART etc) depending on hardware implementation.
> +
> +maintainers:
> +  - Mike Leach <mike.leach@linaro.org>
> +
> +allOf:
> +  - $ref: /schemas/arm/primecell.yaml#
> +
> +# Need a custom select here or 'arm,primecell' will match on lots of nodes
> +select:
> +  properties:
> +    compatible:
> +      contains:
> +        enum:
> +          - arm,coresight-cti
> +  required:
> +    - compatible
> +
> +properties:
> +  $nodename:
> +    pattern: "^cti(@[0-9a-f,]+)*$"
> +  compatible:
> +    items:
> +      - const: arm,coresight-cti
> +      - const: arm,primecell
> +
> +  reg:
> +    items:
> +      - description: device programming registers
> +
> +  arm,cti-v8-arch:
> +    type: boolean
> +    description:
> +      This CTI follows the v8 architecturally mandated layout for a CTI.
> +      Bindings declaring this must declare a cpu, and optionally a single
> +      arm,cs-dev-assoc may be present to define an attached ETM. No additional
> +      trig-conns nodes are permitted. The driver will build a connection model
> +      according to architectural requirements. This will include a filter on
> +      the CPU dbgreq signal as described above.
> +
> +  cpu:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description: Handle to cpu this device is associated with.
> +
> +  arm,cti-ctm-id:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/uint32
> +    description:
> +      Defines the CTM this CTI is connected to, in large systems with multiple
> +      separate CTI/CTM nets. Typically multi-socket systems where the CTM is
> +      propagated between sockets.
> +
> +  arm,cs-dev-assoc:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description:
> +      defines a phandle reference to an associated CoreSight trace device.
> +      When the associated trace device is enabled, then the respective CTI
> +      will be enabled. Use in a trig-conns node, or in CTI base node when
> +      arm,cti-v8-arch present. If the associated device has not been registered
> +      then the node name will be stored as the connection name for later
> +      resolution. If the associated device is not a CoreSight device or not
> +      registered then the node name will remain the connection name and
> +      automatic enabling will not occur.
> +
> +patternProperties:
> +  '^trig_conns@[0-9]+$':
> +    type: object
> +    description:
> +      A trigger connections child node which describes the trigger signals
> +      between this CTI and another hardware device. This device may be a CPU,
> +      CoreSight device, any other hardware device or simple external IO lines.
> +      The connection may have both input and output triggers, or only one or the
> +      other.
> +
> +    properties:
> +
> +      arm,trig-in-sigs:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of CTI trigger in signal numbers in use by a trig-conns node.
> +
> +      arm,trig-in-types:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of constants representing the types for the CTI trigger in
> +          signals. Types in this array match to the corresponding signal in the
> +          arm,trig-in-sigs array. If the -types array is smaller, or omitted
> +          completely, then the types will default to GEN_IO.
> +
> +      arm,trig-out-sigs:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of CTI trigger out signal numbers in use by a trig-conns node.
> +
> +      arm,trig-out-types:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of constants representing the types for the CTI trigger out
> +          signals. Types in this array match to the corresponding signal
> +          in the arm,trig-out-sigs array. If the "-types" array is smaller,
> +          or omitted completely, then the types will default to GEN_IO.
> +
> +      arm,trig-filters:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of CTI trigger out signals that will be blocked from becoming
> +          active, unless filtering is disabled on the driver.
> +
> +      arm,trig-conn-name:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/string
> +        description:
> +          Defines a connection name that will be displayed, if the cpu or
> +          arm,cs-dev-assoc properties are not being used in this connection.
> +          Principle use for CTI that are connected to non-CoreSight devices, or
> +          external IO.
> +
> +    anyOf:
> +      - required:
> +        - arm,trig-in-sigs
> +      - required:
> +        - arm,trig-out-sigs
> +    oneOf:
> +      - required:
> +        - arm,trig-conn-name
> +      - required:
> +        - cpu
> +      - required:
> +        - arm,cs-dev-assoc
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +
> +examples:
> +  # minimum CTI definition. DEVID register used to set number of triggers.
> +  - |
> +    cti@20020000 {
> +      compatible = "arm,coresight-cti", "arm,primecell";
> +      reg = <0x20020000 0x1000>;
> +
> +      clocks = <&soc_smc50mhz>;
> +      clock-names = "apb_pclk";
> +    };
> +  #  v8 architecturally defined CTI - CPU + ETM connections generated by the
> +  #  driver according to the v8 architecture specification.
> +  - |
> +    cti@859000 {
> +      compatible = "arm,coresight-cti", "arm,primecell";
> +      reg = <0x859000 0x1000>;
> +
> +      clocks = <&soc_smc50mhz>;
> +      clock-names = "apb_pclk";
> +
> +      arm,cti-v8-arch;
> +      cpu = <&CPU1>;
> +      arm,cs-dev-assoc = <&etm1>;
> +    };
> +  # Implementation defined CTI - CPU + ETM connections explicitly defined..
> +  # Shows use of type constants from dt-bindings/arm/coresight-cti-dt.h
> +  - |
> +    #include <dt-bindings/arm/coresight-cti-dt.h>
> +
> +    cti@858000 {
> +      compatible = "arm,coresight-cti", "arm,primecell";
> +      reg = <0x858000 0x1000>;
> +
> +      clocks = <&soc_smc50mhz>;
> +      clock-names = "apb_pclk";
> +
> +      arm,cti-ctm-id = <1>;
> +
> +      trig-conns@0 {
> +            arm,trig-in-sigs = <4 5 6 7>;
> +            arm,trig-in-types = <ETM_EXTOUT
> +                                 ETM_EXTOUT
> +                                 ETM_EXTOUT
> +                                 ETM_EXTOUT>;
> +            arm,trig-out-sigs = <4 5 6 7>;
> +            arm,trig-out-types = <ETM_EXTIN
> +                                  ETM_EXTIN
> +                                  ETM_EXTIN
> +                                  ETM_EXTIN>;
> +            arm,cs-dev-assoc = <&etm0>;
> +      };
> +
> +      trig-conns@1 {
> +            cpu = <&CPU0>;
> +            arm,trig-in-sigs = <0 1>;
> +            arm,trig-in-types = <PE_DBGTRIGGER
> +                                 PE_PMUIRQ>;
> +            arm,trig-out-sigs=<0 1 2 >;
> +            arm,trig-out-types = <PE_EDBGREQ
> +                                  PE_DBGRESTART
> +                                  PE_CTIIRQ>;
> +
> +            arm,trig-filters = <0>;
> +      };
> +    };
> +  # Implementation defined CTI - none CoreSight component connections.
> +  - |
> +    cti@20110000 {
> +      compatible = "arm,coresight-cti", "arm,primecell";
> +      reg = <0 0x20110000 0 0x1000>;
> +
> +      clocks = <&soc_smc50mhz>;
> +      clock-names = "apb_pclk";
> +
> +      trig-conns@0 {
> +        arm,trig-in-sigs=<0>;
> +        arm,trig-in-types=<GEN_INTREQ>;
> +        arm,trig-out-sigs=<0>;
> +        arm,trig-out-types=<GEN_HALTREQ>;
> +        arm,trig-conn-name = "sys_profiler";
> +      };
> +
> +      trig-conns@1 {
> +        arm,trig-out-sigs=<2 3>;
> +        arm,trig-out-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> +        arm,trig-conn-name = "watchdog";
> +      };
> +
> +      trig-conns@2 {
> +        arm,trig-in-sigs=<1 6>;
> +        arm,trig-in-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> +        arm,trig-conn-name = "g_counter";
> +      };
> +    };
> +
> +...

I'm not sure what the "..." is there for.  It is not present in the example
schema[1] but I can find the patter in other .yaml files.  As such I will let
Rob decide on that part.

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

[1]. Documentation/devicetree/bindings/example-schema.yaml

> \ No newline at end of file
> diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
> index d02c42d21f2f..846f6daae71b 100644
> --- a/Documentation/devicetree/bindings/arm/coresight.txt
> +++ b/Documentation/devicetree/bindings/arm/coresight.txt
> @@ -45,6 +45,10 @@ its hardware characteristcs.
>  		- Coresight Address Translation Unit (CATU)
>  			"arm,coresight-catu", "arm,primecell";
>  
> +		- Coresight Cross Trigger Interface (CTI):
> +			"arm,coresight-cti", "arm,primecell";
> +			See coresight-cti.yaml for full CTI definitions.
> +
>  	* reg: physical base address and length of the register
>  	  set(s) of the component.
>  
> @@ -72,6 +76,9 @@ its hardware characteristcs.
>  	* reg-names: the only acceptable values are "stm-base" and
>  	  "stm-stimulus-base", each corresponding to the areas defined in "reg".
>  
> +* Required properties for Coresight Cross Trigger Interface (CTI)
> +	See coresight-cti.yaml for full CTI definitions.
> +
>  * Required properties for devices that don't show up on the AMBA bus, such as
>    non-configurable replicators and non-configurable funnels:
>  
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9de89d75dbcc..8d01a74068f7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1608,9 +1608,11 @@ R:	Suzuki K Poulose <suzuki.poulose@arm.com>
>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
>  S:	Maintained
>  F:	drivers/hwtracing/coresight/*
> +F:	include/dt-bindings/arm/coresight-cti-dt.h
>  F:	Documentation/trace/coresight/*
>  F:	Documentation/devicetree/bindings/arm/coresight.txt
>  F:	Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt
> +F:	Documentation/devicetree/bindings/arm/coresight-cti.yaml
>  F:	Documentation/ABI/testing/sysfs-bus-coresight-devices-*
>  F:	tools/perf/arch/arm/util/pmu.c
>  F:	tools/perf/arch/arm/util/auxtrace.c
> diff --git a/include/dt-bindings/arm/coresight-cti-dt.h b/include/dt-bindings/arm/coresight-cti-dt.h
> new file mode 100644
> index 000000000000..61e7bdf8ea6e
> --- /dev/null
> +++ b/include/dt-bindings/arm/coresight-cti-dt.h
> @@ -0,0 +1,37 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * This header provides constants for the defined trigger signal
> + * types on CoreSight CTI.
> + */
> +
> +#ifndef _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
> +#define _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
> +
> +#define GEN_IO		0
> +#define GEN_INTREQ	1
> +#define GEN_INTACK	2
> +#define GEN_HALTREQ	3
> +#define GEN_RESTARTREQ	4
> +#define PE_EDBGREQ	5
> +#define PE_DBGRESTART	6
> +#define PE_CTIIRQ	7
> +#define PE_PMUIRQ	8
> +#define PE_DBGTRIGGER	9
> +#define ETM_EXTOUT	10
> +#define ETM_EXTIN	11
> +#define SNK_FULL	12
> +#define SNK_ACQCOMP	13
> +#define SNK_FLUSHCOMP	14
> +#define SNK_FLUSHIN	15
> +#define SNK_TRIGIN	16
> +#define STM_ASYNCOUT	17
> +#define STM_TOUT_SPTE	18
> +#define STM_TOUT_SW	19
> +#define STM_TOUT_HETE	20
> +#define STM_HWEVENT	21
> +#define ELA_TSTART	22
> +#define ELA_TSTOP	23
> +#define ELA_DBGREQ	24
> +#define CTI_TRIG_MAX	25
> +
> +#endif /*_DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H */
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions.
  2019-11-20 19:06   ` Mathieu Poirier
@ 2019-11-20 22:39     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-20 22:39 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Suzuki K. Poulose

Hi Mathieu,

... is an optional end of document marker in YAML. Seemed to appear in
most of the files I looked at in the devicetree.org  dt-schema project
I looked at so I took it as customary for DT YAML docs.
But as you say - it's up to Rob etc. to approve or otherwise.

Regards

Mike

On Wed, 20 Nov 2019 at 19:06, Mathieu Poirier
<mathieu.poirier@linaro.org> wrote:
>
> On Tue, Nov 19, 2019 at 11:19:03PM +0000, Mike Leach wrote:
> > Adds new coresight-cti.yaml file describing the bindings required to define
> > CTI in the device trees.
> >
> > Adds an include file to dt-bindings/arm to define constants describing
> > common signal functionality used in CoreSight and generic usage.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >  .../bindings/arm/coresight-cti.yaml           | 303 ++++++++++++++++++
> >  .../devicetree/bindings/arm/coresight.txt     |   7 +
> >  MAINTAINERS                                   |   2 +
> >  include/dt-bindings/arm/coresight-cti-dt.h    |  37 +++
> >  4 files changed, 349 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/arm/coresight-cti.yaml
> >  create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h
> >
> > diff --git a/Documentation/devicetree/bindings/arm/coresight-cti.yaml b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> > new file mode 100644
> > index 000000000000..882c72f1c798
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> > @@ -0,0 +1,303 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +# Copyright 2019 Linaro Ltd.
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/arm/coresight-cti.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: ARM Coresight Cross Trigger Interface (CTI) device.
> > +
> > +description: |
> > +  The CoreSight Embedded Cross Trigger (ECT) consists of CTI devices connected
> > +  to one or more CoreSight components and/or a CPU, with CTIs interconnected in
> > +  a star topology via the CTM (which is not programmable). The ECT components
> > +  are not part of the trace generation data path and are thus not part of the
> > +  CoreSight graph described in the general CoreSight bindings file
> > +  coresight.txt.
> > +
> > +  The CTI component properties define the connections between the individual
> > +  CTI and the components it is directly connected to, consisting of input and
> > +  output hardware trigger signals. CTIs can have a maximum number of input and
> > +  output hardware trigger signals (8 each for v1 CTI, 32 each for v2 CTI). The
> > +  number is defined at design time, the maximum of each defined in the DEVID
> > +  register.
> > +
> > +  CTIs are interconnected in a star topology via the CTM, using a number of
> > +  programmable channels usually 4, but again implementation defined and
> > +  described in the DEVID register. The star topology is not required to be
> > +  described in the bindings as the actual connections are software
> > +  programmable.
> > +
> > +  In general the connections between CTI and components via the trigger signals
> > +  are implementation defined, other than when v8 core and ETM is present.
> > +  The v8 architecture defines the required signal connections between CPU core
> > +  and CTI, and ETM and CTI, if the ETM if present.
> > +
> > +  When only minimal information is available for the CTI trigger connections,
> > +  then a minimal driver binding can be declare with no explicit trigger
> > +  signals. This will result in the using the DEVID register to set the
> > +  input and output triggers and channels in use. Any user / client
> > +  application will require additional information on the connections
> > +  between the CTI and other components for correct operation. This minimal
> > +  binding may be used when using the Integration Control registers to
> > +  discover connections between CTI and other CoreSight components,
> > +
> > +  Certain triggers between CoreSight devices and the CTI have specific types
> > +  and usages. These can be defined along with the signal indexes with the
> > +  constants defined in <dt-bindings/arm/coresight-cti-dt.h>
> > +
> > +  For example a CTI connected to a core will usually have a DBGREQ signal. This
> > +  is defined in the binding as type PE_EDBGREQ. These types will appear in an
> > +  optional array alongside the signal indexes. Omitting types will default all
> > +  signals to GEN_IO.
> > +
> > +  Note that some hardware trigger signals can be connected to non-CoreSight
> > +  components (e.g. UART etc) depending on hardware implementation.
> > +
> > +maintainers:
> > +  - Mike Leach <mike.leach@linaro.org>
> > +
> > +allOf:
> > +  - $ref: /schemas/arm/primecell.yaml#
> > +
> > +# Need a custom select here or 'arm,primecell' will match on lots of nodes
> > +select:
> > +  properties:
> > +    compatible:
> > +      contains:
> > +        enum:
> > +          - arm,coresight-cti
> > +  required:
> > +    - compatible
> > +
> > +properties:
> > +  $nodename:
> > +    pattern: "^cti(@[0-9a-f,]+)*$"
> > +  compatible:
> > +    items:
> > +      - const: arm,coresight-cti
> > +      - const: arm,primecell
> > +
> > +  reg:
> > +    items:
> > +      - description: device programming registers
> > +
> > +  arm,cti-v8-arch:
> > +    type: boolean
> > +    description:
> > +      This CTI follows the v8 architecturally mandated layout for a CTI.
> > +      Bindings declaring this must declare a cpu, and optionally a single
> > +      arm,cs-dev-assoc may be present to define an attached ETM. No additional
> > +      trig-conns nodes are permitted. The driver will build a connection model
> > +      according to architectural requirements. This will include a filter on
> > +      the CPU dbgreq signal as described above.
> > +
> > +  cpu:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: Handle to cpu this device is associated with.
> > +
> > +  arm,cti-ctm-id:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/uint32
> > +    description:
> > +      Defines the CTM this CTI is connected to, in large systems with multiple
> > +      separate CTI/CTM nets. Typically multi-socket systems where the CTM is
> > +      propagated between sockets.
> > +
> > +  arm,cs-dev-assoc:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/phandle
> > +    description:
> > +      defines a phandle reference to an associated CoreSight trace device.
> > +      When the associated trace device is enabled, then the respective CTI
> > +      will be enabled. Use in a trig-conns node, or in CTI base node when
> > +      arm,cti-v8-arch present. If the associated device has not been registered
> > +      then the node name will be stored as the connection name for later
> > +      resolution. If the associated device is not a CoreSight device or not
> > +      registered then the node name will remain the connection name and
> > +      automatic enabling will not occur.
> > +
> > +patternProperties:
> > +  '^trig_conns@[0-9]+$':
> > +    type: object
> > +    description:
> > +      A trigger connections child node which describes the trigger signals
> > +      between this CTI and another hardware device. This device may be a CPU,
> > +      CoreSight device, any other hardware device or simple external IO lines.
> > +      The connection may have both input and output triggers, or only one or the
> > +      other.
> > +
> > +    properties:
> > +
> > +      arm,trig-in-sigs:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of CTI trigger in signal numbers in use by a trig-conns node.
> > +
> > +      arm,trig-in-types:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of constants representing the types for the CTI trigger in
> > +          signals. Types in this array match to the corresponding signal in the
> > +          arm,trig-in-sigs array. If the -types array is smaller, or omitted
> > +          completely, then the types will default to GEN_IO.
> > +
> > +      arm,trig-out-sigs:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of CTI trigger out signal numbers in use by a trig-conns node.
> > +
> > +      arm,trig-out-types:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of constants representing the types for the CTI trigger out
> > +          signals. Types in this array match to the corresponding signal
> > +          in the arm,trig-out-sigs array. If the "-types" array is smaller,
> > +          or omitted completely, then the types will default to GEN_IO.
> > +
> > +      arm,trig-filters:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of CTI trigger out signals that will be blocked from becoming
> > +          active, unless filtering is disabled on the driver.
> > +
> > +      arm,trig-conn-name:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/string
> > +        description:
> > +          Defines a connection name that will be displayed, if the cpu or
> > +          arm,cs-dev-assoc properties are not being used in this connection.
> > +          Principle use for CTI that are connected to non-CoreSight devices, or
> > +          external IO.
> > +
> > +    anyOf:
> > +      - required:
> > +        - arm,trig-in-sigs
> > +      - required:
> > +        - arm,trig-out-sigs
> > +    oneOf:
> > +      - required:
> > +        - arm,trig-conn-name
> > +      - required:
> > +        - cpu
> > +      - required:
> > +        - arm,cs-dev-assoc
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
> > +
> > +examples:
> > +  # minimum CTI definition. DEVID register used to set number of triggers.
> > +  - |
> > +    cti@20020000 {
> > +      compatible = "arm,coresight-cti", "arm,primecell";
> > +      reg = <0x20020000 0x1000>;
> > +
> > +      clocks = <&soc_smc50mhz>;
> > +      clock-names = "apb_pclk";
> > +    };
> > +  #  v8 architecturally defined CTI - CPU + ETM connections generated by the
> > +  #  driver according to the v8 architecture specification.
> > +  - |
> > +    cti@859000 {
> > +      compatible = "arm,coresight-cti", "arm,primecell";
> > +      reg = <0x859000 0x1000>;
> > +
> > +      clocks = <&soc_smc50mhz>;
> > +      clock-names = "apb_pclk";
> > +
> > +      arm,cti-v8-arch;
> > +      cpu = <&CPU1>;
> > +      arm,cs-dev-assoc = <&etm1>;
> > +    };
> > +  # Implementation defined CTI - CPU + ETM connections explicitly defined..
> > +  # Shows use of type constants from dt-bindings/arm/coresight-cti-dt.h
> > +  - |
> > +    #include <dt-bindings/arm/coresight-cti-dt.h>
> > +
> > +    cti@858000 {
> > +      compatible = "arm,coresight-cti", "arm,primecell";
> > +      reg = <0x858000 0x1000>;
> > +
> > +      clocks = <&soc_smc50mhz>;
> > +      clock-names = "apb_pclk";
> > +
> > +      arm,cti-ctm-id = <1>;
> > +
> > +      trig-conns@0 {
> > +            arm,trig-in-sigs = <4 5 6 7>;
> > +            arm,trig-in-types = <ETM_EXTOUT
> > +                                 ETM_EXTOUT
> > +                                 ETM_EXTOUT
> > +                                 ETM_EXTOUT>;
> > +            arm,trig-out-sigs = <4 5 6 7>;
> > +            arm,trig-out-types = <ETM_EXTIN
> > +                                  ETM_EXTIN
> > +                                  ETM_EXTIN
> > +                                  ETM_EXTIN>;
> > +            arm,cs-dev-assoc = <&etm0>;
> > +      };
> > +
> > +      trig-conns@1 {
> > +            cpu = <&CPU0>;
> > +            arm,trig-in-sigs = <0 1>;
> > +            arm,trig-in-types = <PE_DBGTRIGGER
> > +                                 PE_PMUIRQ>;
> > +            arm,trig-out-sigs=<0 1 2 >;
> > +            arm,trig-out-types = <PE_EDBGREQ
> > +                                  PE_DBGRESTART
> > +                                  PE_CTIIRQ>;
> > +
> > +            arm,trig-filters = <0>;
> > +      };
> > +    };
> > +  # Implementation defined CTI - none CoreSight component connections.
> > +  - |
> > +    cti@20110000 {
> > +      compatible = "arm,coresight-cti", "arm,primecell";
> > +      reg = <0 0x20110000 0 0x1000>;
> > +
> > +      clocks = <&soc_smc50mhz>;
> > +      clock-names = "apb_pclk";
> > +
> > +      trig-conns@0 {
> > +        arm,trig-in-sigs=<0>;
> > +        arm,trig-in-types=<GEN_INTREQ>;
> > +        arm,trig-out-sigs=<0>;
> > +        arm,trig-out-types=<GEN_HALTREQ>;
> > +        arm,trig-conn-name = "sys_profiler";
> > +      };
> > +
> > +      trig-conns@1 {
> > +        arm,trig-out-sigs=<2 3>;
> > +        arm,trig-out-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> > +        arm,trig-conn-name = "watchdog";
> > +      };
> > +
> > +      trig-conns@2 {
> > +        arm,trig-in-sigs=<1 6>;
> > +        arm,trig-in-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> > +        arm,trig-conn-name = "g_counter";
> > +      };
> > +    };
> > +
> > +...
>
> I'm not sure what the "..." is there for.  It is not present in the example
> schema[1] but I can find the patter in other .yaml files.  As such I will let
> Rob decide on that part.
>
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
> [1]. Documentation/devicetree/bindings/example-schema.yaml
>
> > \ No newline at end of file
> > diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
> > index d02c42d21f2f..846f6daae71b 100644
> > --- a/Documentation/devicetree/bindings/arm/coresight.txt
> > +++ b/Documentation/devicetree/bindings/arm/coresight.txt
> > @@ -45,6 +45,10 @@ its hardware characteristcs.
> >               - Coresight Address Translation Unit (CATU)
> >                       "arm,coresight-catu", "arm,primecell";
> >
> > +             - Coresight Cross Trigger Interface (CTI):
> > +                     "arm,coresight-cti", "arm,primecell";
> > +                     See coresight-cti.yaml for full CTI definitions.
> > +
> >       * reg: physical base address and length of the register
> >         set(s) of the component.
> >
> > @@ -72,6 +76,9 @@ its hardware characteristcs.
> >       * reg-names: the only acceptable values are "stm-base" and
> >         "stm-stimulus-base", each corresponding to the areas defined in "reg".
> >
> > +* Required properties for Coresight Cross Trigger Interface (CTI)
> > +     See coresight-cti.yaml for full CTI definitions.
> > +
> >  * Required properties for devices that don't show up on the AMBA bus, such as
> >    non-configurable replicators and non-configurable funnels:
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 9de89d75dbcc..8d01a74068f7 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -1608,9 +1608,11 @@ R:     Suzuki K Poulose <suzuki.poulose@arm.com>
> >  L:   linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
> >  S:   Maintained
> >  F:   drivers/hwtracing/coresight/*
> > +F:   include/dt-bindings/arm/coresight-cti-dt.h
> >  F:   Documentation/trace/coresight/*
> >  F:   Documentation/devicetree/bindings/arm/coresight.txt
> >  F:   Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt
> > +F:   Documentation/devicetree/bindings/arm/coresight-cti.yaml
> >  F:   Documentation/ABI/testing/sysfs-bus-coresight-devices-*
> >  F:   tools/perf/arch/arm/util/pmu.c
> >  F:   tools/perf/arch/arm/util/auxtrace.c
> > diff --git a/include/dt-bindings/arm/coresight-cti-dt.h b/include/dt-bindings/arm/coresight-cti-dt.h
> > new file mode 100644
> > index 000000000000..61e7bdf8ea6e
> > --- /dev/null
> > +++ b/include/dt-bindings/arm/coresight-cti-dt.h
> > @@ -0,0 +1,37 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * This header provides constants for the defined trigger signal
> > + * types on CoreSight CTI.
> > + */
> > +
> > +#ifndef _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
> > +#define _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
> > +
> > +#define GEN_IO               0
> > +#define GEN_INTREQ   1
> > +#define GEN_INTACK   2
> > +#define GEN_HALTREQ  3
> > +#define GEN_RESTARTREQ       4
> > +#define PE_EDBGREQ   5
> > +#define PE_DBGRESTART        6
> > +#define PE_CTIIRQ    7
> > +#define PE_PMUIRQ    8
> > +#define PE_DBGTRIGGER        9
> > +#define ETM_EXTOUT   10
> > +#define ETM_EXTIN    11
> > +#define SNK_FULL     12
> > +#define SNK_ACQCOMP  13
> > +#define SNK_FLUSHCOMP        14
> > +#define SNK_FLUSHIN  15
> > +#define SNK_TRIGIN   16
> > +#define STM_ASYNCOUT 17
> > +#define STM_TOUT_SPTE        18
> > +#define STM_TOUT_SW  19
> > +#define STM_TOUT_HETE        20
> > +#define STM_HWEVENT  21
> > +#define ELA_TSTART   22
> > +#define ELA_TSTOP    23
> > +#define ELA_DBGREQ   24
> > +#define CTI_TRIG_MAX 25
> > +
> > +#endif /*_DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H */
> > --
> > 2.17.1
> >



-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 01/14] coresight: cti: Initial CoreSight CTI Driver
  2019-11-19 23:18 ` [PATCH v5 01/14] coresight: cti: Initial " Mike Leach
@ 2019-11-21 20:21   ` Mathieu Poirier
  2019-11-29 12:05     ` Mike Leach
  2019-11-25 19:03   ` Suzuki Kuruppassery Poulose
  1 sibling, 1 reply; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-21 20:21 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:18:59PM +0000, Mike Leach wrote:
> This introduces a baseline CTI driver and associated configuration files.
> 
> Uses the platform agnostic naming standard for CoreSight devices, along
> with a generic platform probing method that currently supports device
> tree descriptions, but allows for the ACPI bindings to be added once these
> have been defined for the CTI devices.
> 
> Driver will probe for the device on the AMBA bus, and load the CTI driver
> on CoreSight ID match to CTI IDs in tables.
> 
> Initial sysfs support for enable / disable provided.
> 
> Default CTI interconnection data is generated based on hardware
> register signal counts, with no additional connection information.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  drivers/hwtracing/coresight/Kconfig           |  12 +
>  drivers/hwtracing/coresight/Makefile          |   3 +
>  .../coresight/coresight-cti-platform.c        |  53 +++
>  .../hwtracing/coresight/coresight-cti-sysfs.c |  72 +++
>  drivers/hwtracing/coresight/coresight-cti.c   | 448 ++++++++++++++++++
>  drivers/hwtracing/coresight/coresight-cti.h   | 186 ++++++++
>  drivers/hwtracing/coresight/coresight.c       |   3 +
>  include/linux/coresight.h                     |  23 +
>  8 files changed, 800 insertions(+)
>  create mode 100644 drivers/hwtracing/coresight/coresight-cti-platform.c
>  create mode 100644 drivers/hwtracing/coresight/coresight-cti-sysfs.c
>  create mode 100644 drivers/hwtracing/coresight/coresight-cti.c
>  create mode 100644 drivers/hwtracing/coresight/coresight-cti.h
> 
> diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> index 6ff30e25af55..45d3822c8c8c 100644
> --- a/drivers/hwtracing/coresight/Kconfig
> +++ b/drivers/hwtracing/coresight/Kconfig
> @@ -110,4 +110,16 @@ 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 (CTI) driver"
> +	depends on ARM || ARM64
> +	help
> +	  This driver provides support for CoreSight CTI and CTM components.
> +	  These provide hardware triggering events between CoreSight trace
> +	  source and sink components. These can be used to halt trace or
> +	  inject events into the trace stream. CTI also provides a software
> +	  control to trigger the same halt events. This can provide fast trace
> +	  halt compared to disabling sources and sinks normally in driver
> +	  software.
> +
>  endif
> diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> index 3c0ac421e211..0e3e72f0f510 100644
> --- a/drivers/hwtracing/coresight/Makefile
> +++ b/drivers/hwtracing/coresight/Makefile
> @@ -17,3 +17,6 @@ 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 \
> +				coresight-cti-platform.o \
> +				coresight-cti-sysfs.o
> diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
> new file mode 100644
> index 000000000000..665be86c585d
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
> @@ -0,0 +1,53 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019, The Linaro Limited. All rights reserved.
> + */
> +
> +#include <linux/of.h>
> +
> +#include "coresight-cti.h"
> +
> +/* get the hardware configuration & connection data. */
> +int cti_plat_get_hw_data(struct device *dev,
> +			 struct cti_drvdata *drvdata)
> +{
> +	int rc = 0;
> +	struct cti_device *cti_dev = &drvdata->ctidev;
> +
> +	/* if no connections, just add a single default based on max IN-OUT */
> +	if (cti_dev->nr_trig_con == 0)
> +		rc = cti_add_default_connection(dev, drvdata);
> +	return rc;
> +}
> +
> +struct coresight_platform_data *
> +coresight_cti_get_platform_data(struct device *dev)
> +{
> +	int ret = -ENOENT;
> +	struct coresight_platform_data *pdata = NULL;
> +	struct fwnode_handle *fwnode = dev_fwnode(dev);
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev);
> +
> +	if (IS_ERR_OR_NULL(fwnode))
> +		goto error;
> +
> +	/*
> +	 * Alloc platform data but leave it zero init. CTI does not use the
> +	 * same connection infrastructuree as trace path components but an
> +	 * empty struct enables us to use the standard coresight component
> +	 * registration code.
> +	 */
> +	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata) {
> +		ret = -ENOMEM;
> +		goto error;
> +	}
> +
> +	/* get some CTI specifics */
> +	ret = cti_plat_get_hw_data(dev, drvdata);
> +
> +	if (!ret)
> +		return pdata;
> +error:
> +	return ERR_PTR(ret);
> +}
> diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> new file mode 100644
> index 000000000000..a832b8c6b866
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> @@ -0,0 +1,72 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#include <linux/coresight.h>
> +
> +#include "coresight-cti.h"
> +
> +/* basic attributes */
> +static ssize_t enable_show(struct device *dev,
> +			   struct device_attribute *attr,
> +			   char *buf)
> +{
> +	int enable_req;
> +	bool enabled, powered;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	ssize_t size = 0;
> +
> +	enable_req = atomic_read(&drvdata->config.enable_req_count);
> +	spin_lock(&drvdata->spinlock);
> +	powered = drvdata->config.hw_powered;
> +	enabled = drvdata->config.hw_enabled;
> +	spin_unlock(&drvdata->spinlock);
> +
> +	if (powered) {
> +		size = scnprintf(buf, PAGE_SIZE, "cti %s; powered;\n",
> +				 enabled ? "enabled" : "disabled");
> +	} else {
> +		size = scnprintf(buf, PAGE_SIZE, "cti %s; unpowered;\n",
> +				 enable_req ? "enable req" : "disabled");
> +	}
> +	return size;
> +}
> +
> +static ssize_t enable_store(struct device *dev,
> +			    struct device_attribute *attr,
> +			    const char *buf, size_t size)
> +{
> +	int ret = 0;
> +	unsigned long val;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +
> +	ret = kstrtoul(buf, 0, &val);
> +	if (ret)
> +		return ret;
> +
> +	if (val)
> +		ret = cti_enable(drvdata->csdev);
> +	else
> +		ret = cti_disable(drvdata->csdev);
> +	if (ret)
> +		return ret;
> +	return size;
> +}
> +static DEVICE_ATTR_RW(enable);
> +
> +/* attribute and group sysfs tables. */
> +static struct attribute *coresight_cti_attrs[] = {
> +	&dev_attr_enable.attr,
> +	NULL,
> +};
> +
> +static const struct attribute_group coresight_cti_group = {
> +	.attrs = coresight_cti_attrs,
> +};
> +
> +const struct attribute_group *coresight_cti_groups[] = {
> +	&coresight_cti_group,
> +	NULL,
> +};
> diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> new file mode 100644
> index 000000000000..7ae48bf62d17
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-cti.c
> @@ -0,0 +1,448 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#include "coresight-cti.h"
> +
> +/**
> + * CTI devices can be associated with a PE, or be connected to CoreSight
> + * hardware. We have a list of all CTIs irrespective of CPU bound or
> + * otherwise.
> + *
> + * We assume that the non-CPU CTIs are always powered as we do with sinks etc.
> + *
> + * We leave the client to figure out if all the CTIs are interconnected with
> + * the same CTM, in general this is the case but does not always have to be.
> + */
> +
> +/* net of CTI devices connected via CTM */
> +LIST_HEAD(ect_net);
> +
> +/* protect the list */
> +static DEFINE_MUTEX(ect_mutex);
> +
> +#define csdev_to_cti_drvdata(csdev)	\
> +	dev_get_drvdata(csdev->dev.parent)
> +
> +/*
> + * CTI naming. CTI bound to cores will have the name cti_cpu<N> where
> + * N is the CPU ID. System CTIs will have the name cti_sys<I> where I
> + * is an index allocated by order of discovery.
> + *
> + * CTI device name list - for CTI not bound to cores.
> + */
> +DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys");
> +
> +/* write set of regs to hardware - call with spinlock claimed */
> +void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
> +{
> +	struct cti_config *config = &drvdata->config;
> +	int i;
> +
> +	CS_UNLOCK(drvdata->base);
> +
> +	/* disable CTI before writing registers */
> +	writel_relaxed(0, drvdata->base + CTICONTROL);
> +
> +	/* write the CTI trigger registers */
> +	for (i = 0; i < config->nr_trig_max; i++) {
> +		writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i));
> +		writel_relaxed(config->ctiouten[i],
> +			       drvdata->base + CTIOUTEN(i));
> +	}
> +
> +	/* other regs */
> +	writel_relaxed(config->ctigate, drvdata->base + CTIGATE);
> +	writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
> +	writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);
> +
> +	/* re-enable CTI */
> +	writel_relaxed(1, drvdata->base + CTICONTROL);
> +
> +	CS_LOCK(drvdata->base);
> +}
> +
> +static void cti_enable_hw_smp_call(void *info)
> +{
> +	struct cti_drvdata *drvdata = info;
> +
> +	cti_write_all_hw_regs(drvdata);
> +}
> +
> +/* write regs to hardware and enable */
> +static int cti_enable_hw(struct cti_drvdata *drvdata)
> +{
> +	struct cti_config *config = &drvdata->config;
> +	struct device *dev = &drvdata->csdev->dev;
> +	int rc = 0;
> +
> +	pm_runtime_get_sync(dev->parent);
> +	spin_lock(&drvdata->spinlock);
> +
> +	/* no need to do anything if enabled or unpowered*/
> +	if (config->hw_enabled || !config->hw_powered)
> +		goto cti_state_unchanged;
> +
> +	/* claim the device */
> +	rc = coresight_claim_device(drvdata->base);
> +	if (rc)
> +		goto cti_err_not_enabled;
> +
> +	if (drvdata->ctidev.cpu >= 0) {
> +		rc = smp_call_function_single(drvdata->ctidev.cpu,
> +					      cti_enable_hw_smp_call,
> +					      drvdata, 1);
> +		if (rc)
> +			goto cti_err_not_enabled;
> +	} else {
> +		cti_write_all_hw_regs(drvdata);
> +	}
> +
> +	config->hw_enabled = true;
> +	atomic_inc(&drvdata->config.enable_req_count);
> +	spin_unlock(&drvdata->spinlock);
> +	return rc;
> +
> +cti_state_unchanged:
> +	atomic_inc(&drvdata->config.enable_req_count);
> +
> +	/* cannot enable due to error */
> +cti_err_not_enabled:
> +	spin_unlock(&drvdata->spinlock);
> +	pm_runtime_put(dev->parent);
> +	return rc;
> +}
> +
> +/* disable hardware */
> +static int cti_disable_hw(struct cti_drvdata *drvdata)
> +{
> +	struct cti_config *config = &drvdata->config;
> +	struct device *dev = &drvdata->csdev->dev;
> +
> +	spin_lock(&drvdata->spinlock);
> +
> +	/* check refcount - disable on 0 */
> +	if (atomic_dec_return(&drvdata->config.enable_req_count) > 0)
> +		goto cti_not_disabled;
> +
> +	/* no need to do anything if disabled or cpu unpowered */
> +	if (!config->hw_enabled || !config->hw_powered)
> +		goto cti_not_disabled;
> +
> +	CS_UNLOCK(drvdata->base);
> +
> +	/* disable CTI */
> +	writel_relaxed(0, drvdata->base + CTICONTROL);
> +	config->hw_enabled = false;
> +
> +	coresight_disclaim_device_unlocked(drvdata->base);
> +	CS_LOCK(drvdata->base);
> +	spin_unlock(&drvdata->spinlock);
> +	pm_runtime_put(dev);
> +	return 0;
> +
> +	/* not disabled this call */
> +cti_not_disabled:
> +	spin_unlock(&drvdata->spinlock);
> +	return 0;
> +}
> +
> +/*
> + * Look at the HW DEVID register for some of the HW settings.
> + * DEVID[15:8] - max number of in / out triggers.
> + */
> +#define CTI_DEVID_MAXTRIGS(devid_val) (int)((devid_val & 0xFF00) >> 8)
> +
> +/* DEVID[19:16] - number of CTM channels */
> +#define CTI_DEVID_CTMCHANNELS(devid_val) (int)((devid_val & 0xF0000) >> 16)
> +
> +static void cti_set_default_config(struct device *dev,
> +				   struct cti_drvdata *drvdata)
> +{
> +	struct cti_config *config = &drvdata->config;
> +	u32 devid;
> +
> +	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
> +	config->nr_trig_max = CTI_DEVID_MAXTRIGS(devid);
> +
> +	/*
> +	 * no current hardware should exceed this, but protect the driver
> +	 * in case of fault / out of spec hw
> +	 */
> +	if (config->nr_trig_max > CTIINOUTEN_MAX) {
> +		dev_warn_once(dev,
> +			"Limiting HW MaxTrig value(%d) to driver max(%d)\n",
> +			config->nr_trig_max, CTIINOUTEN_MAX);
> +		config->nr_trig_max = CTIINOUTEN_MAX;
> +	}
> +
> +	config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid);
> +
> +	/* Most regs default to 0 as zalloc'ed except...*/
> +	config->trig_filter_enable = true;
> +	config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
> +	atomic_set(&config->enable_req_count, 0);
> +}
> +
> +/*
> + * Add a connection entry to the list of connections for this
> + * CTI device.
> + */
> +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
> +			     struct cti_trig_con *tc,
> +			     struct coresight_device *csdev,
> +			     const char *assoc_dev_name)
> +{
> +	struct cti_device *cti_dev = &drvdata->ctidev;
> +
> +	tc->con_dev = csdev;
> +	/*
> +	 * Prefer actual associated CS device dev name to supplied value -
> +	 * which is likely to be node name / other conn name.
> +	 */
> +	if (csdev)
> +		tc->con_dev_name = devm_kstrdup(dev,
> +						dev_name(&csdev->dev),
> +						GFP_KERNEL);
> +	else if (assoc_dev_name != NULL)
> +		tc->con_dev_name = devm_kstrdup(dev,
> +						assoc_dev_name, GFP_KERNEL);
> +	list_add_tail(&tc->node, &cti_dev->trig_cons);
> +	cti_dev->nr_trig_con++;
> +
> +	/* add connection usage bit info to overall info */
> +	drvdata->config.trig_in_use |= tc->con_in->used_mask;
> +	drvdata->config.trig_out_use |= tc->con_out->used_mask;
> +
> +	return 0;
> +}
> +
> +/* create a trigger connection with appropriately sized signal groups */
> +struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
> +					   int out_sigs)
> +{
> +	struct cti_trig_con *tc = NULL;
> +	struct cti_trig_grp *in = NULL, *out = NULL;
> +
> +	tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL);
> +	if (!tc)
> +		return tc;
> +
> +	in = devm_kzalloc(dev,
> +			  offsetof(struct cti_trig_grp, sig_types[in_sigs]),
> +			  GFP_KERNEL);
> +	if (!in)
> +		return NULL;
> +
> +	out = devm_kzalloc(dev,
> +			   offsetof(struct cti_trig_grp, sig_types[out_sigs]),
> +			   GFP_KERNEL);
> +	if (!out)
> +		return NULL;
> +
> +	tc->con_in = in;
> +	tc->con_out = out;
> +	tc->con_in->nr_sigs = in_sigs;
> +	tc->con_out->nr_sigs = out_sigs;
> +	return tc;
> +}
> +
> +/*
> + * Add a default connection if nothing else is specified.
> + * single connection based on max in/out info, no assoc device
> + */
> +int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
> +{
> +	int ret = 0;
> +	int n_trigs = drvdata->config.nr_trig_max;
> +	u32 n_trig_mask = GENMASK(n_trigs - 1, 0);
> +	struct cti_trig_con *tc = NULL;
> +
> +	/*
> +	 * Assume max trigs for in and out,
> +	 * all used, default sig types allocated
> +	 */
> +	tc = cti_allocate_trig_con(dev, n_trigs, n_trigs);
> +	if (!tc)
> +		return -ENOMEM;
> +
> +	tc->con_in->used_mask = n_trig_mask;
> +	tc->con_out->used_mask = n_trig_mask;
> +	ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default");
> +	return ret;
> +}
> +
> +/** cti ect operations **/
> +int cti_enable(struct coresight_device *csdev)
> +{
> +	struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> +
> +	/* enable hardware with refcount */
> +	return cti_enable_hw(drvdata);
> +}
> +
> +int cti_disable(struct coresight_device *csdev)
> +{
> +	struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> +
> +	/* disable hardware with refcount */
> +	return cti_disable_hw(drvdata);
> +}
> +
> +const struct coresight_ops_ect cti_ops_ect = {
> +	.enable = cti_enable,
> +	.disable = cti_disable,
> +};
> +
> +const struct coresight_ops cti_ops = {
> +	.ect_ops = &cti_ops_ect,
> +};
> +
> +/*
> + * Free up CTI specific resources
> + * called by dev->release, need to call down to underlying csdev release.
> + */
> +static void cti_device_release(struct device *dev)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_drvdata *ect_item, *ect_tmp;
> +
> +	mutex_lock(&ect_mutex);
> +
> +	/* remove from the list */
> +	list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
> +		if (ect_item == drvdata) {
> +			list_del(&ect_item->node);
> +			break;
> +		}
> +	}
> +	mutex_unlock(&ect_mutex);
> +
> +	if (drvdata->csdev_release)
> +		drvdata->csdev_release(dev);
> +}
> +
> +static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> +{
> +	int ret = 0;
> +	void __iomem *base;
> +	struct device *dev = &adev->dev;
> +	struct cti_drvdata *drvdata = NULL;
> +	struct coresight_desc cti_desc;
> +	struct coresight_platform_data *pdata = NULL;
> +	struct resource *res = &adev->res;
> +
> +	/* driver data*/
> +	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> +	if (!drvdata) {
> +		ret = -ENOMEM;
> +		dev_info(dev, "%s, mem err\n", __func__);
> +		goto err_out;
> +	}
> +
> +	/* Validity for the resource is already checked by the AMBA core */
> +	base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(base)) {
> +		ret = PTR_ERR(base);
> +		dev_info(dev, "%s, remap err\n", __func__);
> +		goto err_out;
> +	}
> +	drvdata->base = base;
> +
> +	dev_set_drvdata(dev, drvdata);
> +
> +	/* default CTI device info  */
> +	drvdata->ctidev.cpu = -1;
> +	drvdata->ctidev.nr_trig_con = 0;
> +	drvdata->ctidev.ctm_id = 0;
> +	INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);
> +
> +	spin_lock_init(&drvdata->spinlock);
> +
> +	/* initialise CTI driver config values */
> +	cti_set_default_config(dev, drvdata);
> +
> +	/* Parse the .dts for connections and signals */
> +	pdata = coresight_cti_get_platform_data(dev);

Here I would simply call cti_plat_get_hw_data() and not instantiate a *pdata.
See below for more details.

> +	if (IS_ERR(pdata)) {
> +		dev_info(dev, "coresight_cti_get_platform_data err\n");
> +		ret =  PTR_ERR(pdata);
> +		goto err_out;
> +	}
> +
> +	/* default to powered - could change on PM notifications */
> +	drvdata->config.hw_powered = true;
> +
> +	/* set up device name - will depend if cpu bound or otherwise */
> +	if (drvdata->ctidev.cpu >= 0)
> +		cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d",
> +					       drvdata->ctidev.cpu);
> +	else
> +		cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev);
> +	if (!cti_desc.name) {
> +		ret = -ENOMEM;
> +		goto err_out;
> +	}
> +
> +	/* set up coresight component description */
> +	cti_desc.pdata = pdata;

Just set this to NULL and add a check in coresight_release_platform_data() that
returns immediately if @pdata is NULL.  The latter should be done in a separate
patch preceding this one.  If someone tries to do a cti_drvdata::csdev::pdata,
we'll find out pretty quickly. 

With this:
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

> +	cti_desc.type = CORESIGHT_DEV_TYPE_ECT;
> +	cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI;
> +	cti_desc.ops = &cti_ops;
> +	cti_desc.groups = coresight_cti_groups;
> +	cti_desc.dev = dev;
> +	drvdata->csdev = coresight_register(&cti_desc);
> +	if (IS_ERR(drvdata->csdev)) {
> +		ret = PTR_ERR(drvdata->csdev);
> +		goto err_out;
> +	}
> +
> +	/* add to list of CTI devices */
> +	mutex_lock(&ect_mutex);
> +	list_add(&drvdata->node, &ect_net);
> +	mutex_unlock(&ect_mutex);
> +
> +	/* set up release chain */
> +	drvdata->csdev_release = drvdata->csdev->dev.release;
> +	drvdata->csdev->dev.release = cti_device_release;
> +
> +	/* all done - dec pm refcount */
> +	pm_runtime_put(&adev->dev);
> +	dev_info(&drvdata->csdev->dev, "CTI initialized\n");
> +	return 0;
> +
> +err_out:
> +	return ret;
> +}
> +
> +static struct amba_cs_uci_id uci_id_cti[] = {
> +	{
> +		/*  CTI UCI data */
> +		.devarch	= 0x47701a14, /* CTI v2 */
> +		.devarch_mask	= 0xfff0ffff,
> +		.devtype	= 0x00000014, /* maj(0x4-debug) min(0x1-ECT) */
> +	}
> +};
> +
> +static const struct amba_id cti_ids[] = {
> +	CS_AMBA_ID(0x000bb906), /* Coresight CTI (SoC 400), C-A72, C-A57 */
> +	CS_AMBA_ID(0x000bb922), /* CTI - C-A8 */
> +	CS_AMBA_ID(0x000bb9a8), /* CTI - C-A53 */
> +	CS_AMBA_ID(0x000bb9aa), /* CTI - C-A73 */
> +	CS_AMBA_UCI_ID(0x000bb9da, uci_id_cti), /* CTI - C-A35 */
> +	CS_AMBA_UCI_ID(0x000bb9ed, uci_id_cti), /* Coresight CTI (SoC 600) */
> +	{ 0, 0},
> +};
> +
> +static struct amba_driver cti_driver = {
> +	.drv = {
> +		.name	= "coresight-cti",
> +		.owner = THIS_MODULE,
> +		.suppress_bind_attrs = true,
> +	},
> +	.probe		= cti_probe,
> +	.id_table	= cti_ids,
> +};
> +builtin_amba_driver(cti_driver);
> diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
> new file mode 100644
> index 000000000000..e0d476533a82
> --- /dev/null
> +++ b/drivers/hwtracing/coresight/coresight-cti.h
> @@ -0,0 +1,186 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (c) 2018 Linaro Limited, All rights reserved.
> + * Author: Mike Leach <mike.leach@linaro.org>
> + */
> +
> +#ifndef _CORESIGHT_CORESIGHT_CTI_H
> +#define _CORESIGHT_CORESIGHT_CTI_H
> +
> +#include <asm/local.h>
> +#include <linux/spinlock.h>
> +#include "coresight-priv.h"
> +
> +/*
> + * Device registers
> + * 0x000 - 0x144: CTI programming and status
> + * 0xEDC - 0xEF8: CTI integration test.
> + * 0xF00 - 0xFFC: Coresight management registers.
> + */
> +/* CTI programming registers */
> +#define CTICONTROL		0x000
> +#define CTIINTACK		0x010
> +#define CTIAPPSET		0x014
> +#define CTIAPPCLEAR		0x018
> +#define CTIAPPPULSE		0x01C
> +#define CTIINEN(n)		(0x020 + (4 * n))
> +#define CTIOUTEN(n)		(0x0A0 + (4 * n))
> +#define CTITRIGINSTATUS		0x130
> +#define CTITRIGOUTSTATUS	0x134
> +#define CTICHINSTATUS		0x138
> +#define CTICHOUTSTATUS		0x13C
> +#define CTIGATE			0x140
> +#define ASICCTL			0x144
> +/* Integration test registers */
> +#define ITCHINACK		0xEDC /* WO CTI CSSoc 400 only*/
> +#define ITTRIGINACK		0xEE0 /* WO CTI CSSoc 400 only*/
> +#define ITCHOUT			0xEE4 /* WO RW-600 */
> +#define ITTRIGOUT		0xEE8 /* WO RW-600 */
> +#define ITCHOUTACK		0xEEC /* RO CTI CSSoc 400 only*/
> +#define ITTRIGOUTACK		0xEF0 /* RO CTI CSSoc 400 only*/
> +#define ITCHIN			0xEF4 /* RO */
> +#define ITTRIGIN		0xEF8 /* RO */
> +/* management registers */
> +#define CTIDEVAFF0		0xFA8
> +#define CTIDEVAFF1		0xFAC
> +
> +/*
> + * CTI CSSoc 600 has a max of 32 trigger signals per direction.
> + * CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def.
> + * Max of in and out defined in the DEVID register.
> + * - pick up actual number used from .dts parameters if present.
> + */
> +#define CTIINOUTEN_MAX		32
> +
> +/**
> + * Group of related trigger signals
> + *
> + * @nr_sigs: number of signals in the group.
> + * @used_mask: bitmask representing the signal indexes in the group.
> + * @sig_types: array of types for the signals, length nr_sigs.
> + */
> +struct cti_trig_grp {
> +	int nr_sigs;
> +	u32 used_mask;
> +	int sig_types[0];
> +};
> +
> +/**
> + * Trigger connection - connection between a CTI and other (coresight) device
> + * lists input and output trigger signals for the device
> + *
> + * @con_in: connected CTIIN signals for the device.
> + * @con_out: connected CTIOUT signals for the device.
> + * @con_dev: coresight device connected to the CTI, NULL if not CS device
> + * @con_dev_name: name of connected device (CS or CPU)
> + * @node: entry node in list of connections.
> + */
> +struct cti_trig_con {
> +	struct cti_trig_grp *con_in;
> +	struct cti_trig_grp *con_out;
> +	struct coresight_device *con_dev;
> +	char *con_dev_name;
> +	struct list_head node;
> +};
> +
> +/**
> + * struct cti_device - description of CTI device properties.
> + *
> + * @nt_trig_con: Number of external devices connected to this device.
> + * @ctm_id: which CTM this device is connected to (by default it is
> + *          assumed there is a single CTM per SoC, ID 0).
> + * @trig_cons: list of connections to this device.
> + * @cpu: CPU ID if associated with CPU, -1 otherwise.
> + */
> +struct cti_device {
> +	int nr_trig_con;
> +	u32 ctm_id;
> +	struct list_head trig_cons;
> +	int cpu;
> +};
> +
> +/**
> + * struct cti_config - configuration of the CTI device hardware
> + *
> + * @nr_trig_max: Max number of trigger signals implemented on device.
> + *		 (max of trig_in or trig_out) - from ID register.
> + * @nr_ctm_channels: number of available CTM channels - from ID register.
> + * @enable_req_count: CTI is enabled alongside >=1 associated devices.
> + * @hw_enabled: true if hw is currently enabled.
> + * @hw_powered: true if associated cpu powered on, or no cpu.
> + * @trig_in_use: bitfield of in triggers registered as in use.
> + * @trig_out_use: bitfield of out triggers registered as in use.
> + * @trig_out_filter: bitfield of out triggers that are blocked if filter
> + *	             enabled. Typically this would be dbgreq / restart on
> + *		     a core CTI.
> + * @trig_filter_enable: 1 if filtering enabled.
> + * @xtrig_rchan_sel: channel selection for xtrigger connection show.
> + * @ctiappset: CTI Software application channel set.
> + * @ctiinout_sel: register selector for INEN and OUTEN regs.
> + * @ctiinen: enable input trigger to a channel.
> + * @ctiouten: enable output trigger from a channel.
> + * @ctigate: gate channel output from CTI to CTM.
> + * @asicctl: asic control register.
> + */
> +struct cti_config {
> +	/* hardware description */
> +	int nr_ctm_channels;
> +	int nr_trig_max;
> +
> +	/* cti enable control */
> +	atomic_t enable_req_count;
> +	bool hw_enabled;
> +	bool hw_powered;
> +
> +	/* registered triggers and filtering */
> +	u32 trig_in_use;
> +	u32 trig_out_use;
> +	u32 trig_out_filter;
> +	bool trig_filter_enable;
> +	u8 xtrig_rchan_sel;
> +
> +	/* cti cross trig programmable regs */
> +	u32 ctiappset;
> +	u8 ctiinout_sel;
> +	u32 ctiinen[CTIINOUTEN_MAX];
> +	u32 ctiouten[CTIINOUTEN_MAX];
> +	u32 ctigate;
> +	u32 asicctl;
> +};
> +
> +/**
> + * struct cti_drvdata - specifics for the CTI device
> + * @base:	Memory mapped base address for this component..
> + * @csdev:	Standard CoreSight device information.
> + * @ctidev:	Extra information needed by the CTI/CTM framework.
> + * @spinlock:	Control data access to one at a time.
> + * @config:	Configuration data for this CTI device.
> + * @node:	List entry of this device in the list of CTI devices.
> + * @csdev_release: release function for underlying coresight_device.
> + */
> +struct cti_drvdata {
> +	void __iomem *base;
> +	struct coresight_device	*csdev;
> +	struct cti_device ctidev;
> +	spinlock_t spinlock;
> +	struct cti_config config;
> +	struct list_head node;
> +	void (*csdev_release)(struct device *dev);
> +};
> +
> +/* private cti driver fns & vars */
> +extern const struct attribute_group *coresight_cti_groups[];
> +int cti_add_default_connection(struct device *dev,
> +			       struct cti_drvdata *drvdata);
> +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
> +			     struct cti_trig_con *tc,
> +			     struct coresight_device *csdev,
> +			     const char *assoc_dev_name);
> +struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
> +					   int out_sigs);
> +int cti_enable(struct coresight_device *csdev);
> +int cti_disable(struct coresight_device *csdev);
> +struct coresight_platform_data *
> +coresight_cti_get_platform_data(struct device *dev);
> +
> +#endif  /* _CORESIGHT_CORESIGHT_CTI_H */
> diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
> index ef20f74c85fa..1a5fdf2710ff 100644
> --- a/drivers/hwtracing/coresight/coresight.c
> +++ b/drivers/hwtracing/coresight/coresight.c
> @@ -955,6 +955,9 @@ static struct device_type coresight_dev_type[] = {
>  	{
>  		.name = "helper",
>  	},
> +	{
> +		.name = "ect",
> +	},
>  };
>  
>  static void coresight_device_release(struct device *dev)
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index 44e552de419c..b3e582d96a34 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -41,6 +41,7 @@ enum coresight_dev_type {
>  	CORESIGHT_DEV_TYPE_LINKSINK,
>  	CORESIGHT_DEV_TYPE_SOURCE,
>  	CORESIGHT_DEV_TYPE_HELPER,
> +	CORESIGHT_DEV_TYPE_ECT,
>  };
>  
>  enum coresight_dev_subtype_sink {
> @@ -68,6 +69,12 @@ enum coresight_dev_subtype_helper {
>  	CORESIGHT_DEV_SUBTYPE_HELPER_CATU,
>  };
>  
> +/* Embedded Cross Trigger (ECT) sub-types */
> +enum coresight_dev_subtype_ect {
> +	CORESIGHT_DEV_SUBTYPE_ECT_NONE,
> +	CORESIGHT_DEV_SUBTYPE_ECT_CTI,
> +};
> +
>  /**
>   * union coresight_dev_subtype - further characterisation of a type
>   * @sink_subtype:	type of sink this component is, as defined
> @@ -78,6 +85,8 @@ enum coresight_dev_subtype_helper {
>   *			by @coresight_dev_subtype_source.
>   * @helper_subtype:	type of helper this component is, as defined
>   *			by @coresight_dev_subtype_helper.
> + * @ect_subtype:        type of cross trigger this component is, as
> + *			defined by @coresight_dev_subtype_ect
>   */
>  union coresight_dev_subtype {
>  	/* We have some devices which acts as LINK and SINK */
> @@ -87,6 +96,7 @@ union coresight_dev_subtype {
>  	};
>  	enum coresight_dev_subtype_source source_subtype;
>  	enum coresight_dev_subtype_helper helper_subtype;
> +	enum coresight_dev_subtype_ect ect_subtype;
>  };
>  
>  /**
> @@ -196,6 +206,7 @@ static struct coresight_dev_list (var) = {				\
>  #define sink_ops(csdev)		csdev->ops->sink_ops
>  #define link_ops(csdev)		csdev->ops->link_ops
>  #define helper_ops(csdev)	csdev->ops->helper_ops
> +#define ect_ops(csdev)		csdev->ops->ect_ops
>  
>  /**
>   * struct coresight_ops_sink - basic operations for a sink
> @@ -262,11 +273,23 @@ struct coresight_ops_helper {
>  	int (*disable)(struct coresight_device *csdev, void *data);
>  };
>  
> +/**
> + * struct coresight_ops_ect - Ops for an embedded cross trigger device
> + *
> + * @enable	: Enable the device
> + * @disable	: Disable the device
> + */
> +struct coresight_ops_ect {
> +	int (*enable)(struct coresight_device *csdev);
> +	int (*disable)(struct coresight_device *csdev);
> +};
> +
>  struct coresight_ops {
>  	const struct coresight_ops_sink *sink_ops;
>  	const struct coresight_ops_link *link_ops;
>  	const struct coresight_ops_source *source_ops;
>  	const struct coresight_ops_helper *helper_ops;
> +	const struct coresight_ops_ect *ect_ops;
>  };
>  
>  #ifdef CONFIG_CORESIGHT
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 02/14] coresight: cti: Add sysfs coresight mgmt reg access.
  2019-11-19 23:19 ` [PATCH v5 02/14] coresight: cti: Add sysfs coresight mgmt reg access Mike Leach
@ 2019-11-22 17:19   ` Mathieu Poirier
  0 siblings, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-22 17:19 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:00PM +0000, Mike Leach wrote:
> Adds sysfs access to the coresight management registers.
> 
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> Signed-off-by: Mike Leach <mike.leach@linaro.org>

Tags added to a patch are like a chain of custody and should be added in order
they were published.  In this case you wrote the patch so your SoB goes first.
Then Suzuki and I have reviewed your patch and as such, our RB come _after_ your
SoB.  When I add the patch to my tree I'll add my SoB after that and when Greg
picks it up in his, he will do the same.  Please re-order the tags in this patch
and the other ones in this set to reflect the chronology of events.

> ---
>  .../hwtracing/coresight/coresight-cti-sysfs.c | 53 +++++++++++++++++++
>  drivers/hwtracing/coresight/coresight-priv.h  |  1 +
>  2 files changed, 54 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> index a832b8c6b866..507f8eb487fe 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> @@ -62,11 +62,64 @@ static struct attribute *coresight_cti_attrs[] = {
>  	NULL,
>  };
>  
> +/* register based attributes */
> +
> +/* macro to access RO registers with power check only (no enable check). */
> +#define coresight_cti_reg(name, offset)			\
> +static ssize_t name##_show(struct device *dev,				\
> +			   struct device_attribute *attr, char *buf)	\
> +{									\
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);	\
> +	u32 val = 0;							\
> +	pm_runtime_get_sync(dev->parent);				\
> +	spin_lock(&drvdata->spinlock);					\
> +	if (drvdata->config.hw_powered)					\
> +		val = readl_relaxed(drvdata->base + offset);		\
> +	spin_unlock(&drvdata->spinlock);				\
> +	pm_runtime_put_sync(dev->parent);				\
> +	return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);		\
> +}									\
> +static DEVICE_ATTR_RO(name)
> +
> +/* coresight management registers */
> +coresight_cti_reg(devaff0, CTIDEVAFF0);
> +coresight_cti_reg(devaff1, CTIDEVAFF1);
> +coresight_cti_reg(authstatus, CORESIGHT_AUTHSTATUS);
> +coresight_cti_reg(devarch, CORESIGHT_DEVARCH);
> +coresight_cti_reg(devid, CORESIGHT_DEVID);
> +coresight_cti_reg(devtype, CORESIGHT_DEVTYPE);
> +coresight_cti_reg(pidr0, CORESIGHT_PERIPHIDR0);
> +coresight_cti_reg(pidr1, CORESIGHT_PERIPHIDR1);
> +coresight_cti_reg(pidr2, CORESIGHT_PERIPHIDR2);
> +coresight_cti_reg(pidr3, CORESIGHT_PERIPHIDR3);
> +coresight_cti_reg(pidr4, CORESIGHT_PERIPHIDR4);
> +
> +static struct attribute *coresight_cti_mgmt_attrs[] = {
> +	&dev_attr_devaff0.attr,
> +	&dev_attr_devaff1.attr,
> +	&dev_attr_authstatus.attr,
> +	&dev_attr_devarch.attr,
> +	&dev_attr_devid.attr,
> +	&dev_attr_devtype.attr,
> +	&dev_attr_pidr0.attr,
> +	&dev_attr_pidr1.attr,
> +	&dev_attr_pidr2.attr,
> +	&dev_attr_pidr3.attr,
> +	&dev_attr_pidr4.attr,
> +	NULL,
> +};
> +
>  static const struct attribute_group coresight_cti_group = {
>  	.attrs = coresight_cti_attrs,
>  };
>  
> +static const struct attribute_group coresight_cti_mgmt_group = {
> +	.attrs = coresight_cti_mgmt_attrs,
> +	.name = "mgmt",
> +};
> +
>  const struct attribute_group *coresight_cti_groups[] = {
>  	&coresight_cti_group,
> +	&coresight_cti_mgmt_group,
>  	NULL,
>  };
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index 82e563cdc879..aba6b789c969 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -22,6 +22,7 @@
>  #define CORESIGHT_CLAIMCLR	0xfa4
>  #define CORESIGHT_LAR		0xfb0
>  #define CORESIGHT_LSR		0xfb4
> +#define CORESIGHT_DEVARCH	0xfbc
>  #define CORESIGHT_AUTHSTATUS	0xfb8
>  #define CORESIGHT_DEVID		0xfc8
>  #define CORESIGHT_DEVTYPE	0xfcc
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 04/14] coresight: cti: Add sysfs trigger / channel programming API
  2019-11-19 23:19 ` [PATCH v5 04/14] coresight: cti: Add sysfs trigger / channel programming API Mike Leach
@ 2019-11-22 18:40   ` Mathieu Poirier
  2019-11-27 18:40   ` Suzuki Kuruppassery Poulose
  1 sibling, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-22 18:40 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:02PM +0000, Mike Leach wrote:
> Adds a user API to allow programming of CTI by trigger ID and
> channel number. This will take the channel and trigger ID supplied
> by the user and program the appropriate register values.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  .../hwtracing/coresight/coresight-cti-sysfs.c | 349 ++++++++++++++++++
>  drivers/hwtracing/coresight/coresight-cti.c   | 147 ++++++++
>  drivers/hwtracing/coresight/coresight-cti.h   |  32 ++
>  3 files changed, 528 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> index 02d3ee0c1278..98de8a4768fc 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> @@ -464,6 +464,349 @@ static struct attribute *coresight_cti_regs_attrs[] = {
>  	NULL,
>  };
>  
> +/* CTI channel x-trigger programming */
> +static int
> +cti_trig_op_parse(struct device *dev, enum cti_chan_op op,
> +		  enum cti_trig_dir dir, const char *buf, size_t size)
> +{
> +	u32 chan_idx;
> +	u32 trig_idx;
> +	int items, err = -EINVAL;
> +
> +	/* extract chan idx and trigger idx */
> +	items = sscanf(buf, "%d %d", &chan_idx, &trig_idx);
> +	if (items == 2) {
> +		err = cti_channel_trig_op(dev, op, dir, chan_idx, trig_idx);
> +		if (!err)
> +			err = size;
> +	}
> +	return err;
> +}
> +
> +static ssize_t trigin_attach_store(struct device *dev,
> +				   struct device_attribute *attr,
> +				   const char *buf, size_t size)
> +{
> +	return cti_trig_op_parse(dev, CTI_CHAN_ATTACH, CTI_TRIG_IN,
> +				 buf, size);
> +}
> +static DEVICE_ATTR_WO(trigin_attach);
> +
> +static ssize_t trigin_detach_store(struct device *dev,
> +				   struct device_attribute *attr,
> +				   const char *buf, size_t size)
> +{
> +	return cti_trig_op_parse(dev, CTI_CHAN_DETACH, CTI_TRIG_IN,
> +				 buf, size);
> +}
> +static DEVICE_ATTR_WO(trigin_detach);
> +
> +static ssize_t trigout_attach_store(struct device *dev,
> +				    struct device_attribute *attr,
> +				    const char *buf, size_t size)
> +{
> +	return cti_trig_op_parse(dev, CTI_CHAN_ATTACH, CTI_TRIG_OUT,
> +				 buf, size);
> +}
> +static DEVICE_ATTR_WO(trigout_attach);
> +
> +static ssize_t trigout_detach_store(struct device *dev,
> +				    struct device_attribute *attr,
> +				    const char *buf, size_t size)
> +{
> +	return cti_trig_op_parse(dev, CTI_CHAN_DETACH, CTI_TRIG_OUT,
> +				 buf, size);
> +}
> +static DEVICE_ATTR_WO(trigout_detach);
> +
> +
> +static ssize_t chan_gate_enable_store(struct device *dev,
> +				      struct device_attribute *attr,
> +				      const char *buf, size_t size)
> +{
> +	int err = 0, channel = 0;
> +
> +	if (kstrtoint(buf, 0, &channel))
> +		return -EINVAL;
> +
> +	err = cti_channel_gate_op(dev, CTI_GATE_CHAN_ENABLE, channel);
> +	return err ? err : size;
> +}
> +
> +static ssize_t chan_gate_enable_show(struct device *dev,
> +				     struct device_attribute *attr,
> +				     char *buf)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *cfg = &drvdata->config;
> +	unsigned long ctigate_bitmask = cfg->ctigate;
> +	int size = 0;
> +
> +	if (cfg->ctigate == 0)
> +		size = scnprintf(buf, PAGE_SIZE, "\n");
> +	else
> +		size = bitmap_print_to_pagebuf(true, buf, &ctigate_bitmask,
> +					       cfg->nr_ctm_channels);
> +	return size;
> +}
> +static DEVICE_ATTR_RW(chan_gate_enable);
> +
> +static ssize_t chan_gate_disable_store(struct device *dev,
> +				       struct device_attribute *attr,
> +				       const char *buf, size_t size)
> +{
> +	int err = 0, channel = 0;
> +
> +	if (kstrtoint(buf, 0, &channel))
> +		return -EINVAL;
> +
> +	err = cti_channel_gate_op(dev, CTI_GATE_CHAN_DISABLE, channel);
> +	return err ? err : size;
> +}
> +static DEVICE_ATTR_WO(chan_gate_disable);
> +
> +static int
> +chan_op_parse(struct device *dev, enum cti_chan_set_op op, const char *buf)
> +{
> +	int err = 0, channel = 0;
> +
> +	if (kstrtoint(buf, 0, &channel))
> +		return -EINVAL;
> +
> +	err = cti_channel_setop(dev, op, channel);
> +	return err;
> +
> +}
> +
> +static ssize_t chan_set_store(struct device *dev,
> +			      struct device_attribute *attr,
> +			      const char *buf, size_t size)
> +{
> +	int err = chan_op_parse(dev, CTI_CHAN_SET, buf);
> +
> +	return err ? err : size;
> +}
> +static DEVICE_ATTR_WO(chan_set);
> +
> +static ssize_t chan_clear_store(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf, size_t size)
> +{
> +	int err = chan_op_parse(dev, CTI_CHAN_CLR, buf);
> +
> +	return err ? err : size;
> +}
> +static DEVICE_ATTR_WO(chan_clear);
> +
> +static ssize_t chan_pulse_store(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf, size_t size)
> +{
> +	int err = chan_op_parse(dev, CTI_CHAN_PULSE, buf);
> +
> +	return err ? err : size;
> +}
> +static DEVICE_ATTR_WO(chan_pulse);
> +
> +static ssize_t trig_filter_enable_show(struct device *dev,
> +				       struct device_attribute *attr,
> +				       char *buf)
> +{
> +	u32 val;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +
> +	spin_lock(&drvdata->spinlock);
> +	val = drvdata->config.trig_filter_enable;
> +	spin_unlock(&drvdata->spinlock);
> +	return scnprintf(buf, PAGE_SIZE, "%d\n", val);
> +}
> +
> +static ssize_t trig_filter_enable_store(struct device *dev,
> +					struct device_attribute *attr,
> +					const char *buf, size_t size)
> +{
> +	unsigned long val;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +
> +	if (kstrtoul(buf, 0, &val))
> +		return -EINVAL;
> +
> +	spin_lock(&drvdata->spinlock);
> +	drvdata->config.trig_filter_enable = !!val;
> +	spin_unlock(&drvdata->spinlock);
> +	return size;
> +}
> +static DEVICE_ATTR_RW(trig_filter_enable);
> +
> +static ssize_t trigout_filtered_show(struct device *dev,
> +				     struct device_attribute *attr,
> +				     char *buf)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *cfg = &drvdata->config;
> +	int size = 0, nr_trig_max = cfg->nr_trig_max;
> +	unsigned long mask = cfg->trig_out_filter;
> +
> +	if (mask)
> +		size = bitmap_print_to_pagebuf(true, buf, &mask, nr_trig_max);
> +	return size;
> +}
> +static DEVICE_ATTR_RO(trigout_filtered);
> +
> +/* clear all xtrigger / channel programming */
> +static ssize_t chan_xtrigs_reset_store(struct device *dev,
> +				       struct device_attribute *attr,
> +				       const char *buf, size_t size)
> +{
> +	int i;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *config = &drvdata->config;
> +
> +	spin_lock(&drvdata->spinlock);
> +
> +	/* clear the CTI trigger / channel programming registers */
> +	for (i = 0; i < config->nr_trig_max; i++) {
> +		config->ctiinen[i] = 0;
> +		config->ctiouten[i] = 0;
> +	}
> +
> +	/* clear the other regs */
> +	config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
> +	config->asicctl = 0;
> +	config->ctiappset = 0;
> +	config->ctiinout_sel = 0;
> +	config->xtrig_rchan_sel = 0;
> +
> +	/* if enabled then write through */
> +	if (CTI_PWR_ENA(config))
> +		cti_write_all_hw_regs(drvdata);
> +
> +	spin_unlock(&drvdata->spinlock);
> +	return size;
> +}
> +static DEVICE_ATTR_WO(chan_xtrigs_reset);
> +
> +/*
> + * Write to select a channel to view, read to display the
> + * cross triggers for the selected channel.
> + */
> +static ssize_t chan_xtrigs_view_store(struct device *dev,
> +				      struct device_attribute *attr,
> +				      const char *buf, size_t size)
> +{
> +	unsigned long val;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +
> +	if (kstrtoul(buf, 0, &val))
> +		return -EINVAL;
> +	if (val > (drvdata->config.nr_ctm_channels - 1))
> +		return -EINVAL;
> +
> +	spin_lock(&drvdata->spinlock);
> +	drvdata->config.xtrig_rchan_sel = val;
> +	spin_unlock(&drvdata->spinlock);
> +	return size;
> +}
> +
> +static ssize_t chan_xtrigs_view_show(struct device *dev,
> +				     struct device_attribute *attr,
> +				     char *buf)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *cfg = &drvdata->config;
> +	int used = 0, reg_idx;
> +	int buf_sz = PAGE_SIZE;
> +	u32 chan_mask = BIT(cfg->xtrig_rchan_sel);
> +
> +	used += scnprintf(buf, buf_sz, "[%d] IN: ", cfg->xtrig_rchan_sel);
> +	for (reg_idx = 0;
> +	     reg_idx < drvdata->config.nr_trig_max;
> +	     reg_idx++) {
> +		if (chan_mask & cfg->ctiinen[reg_idx]) {
> +			used += scnprintf(buf + used, buf_sz - used, "%d ",
> +					  reg_idx);
> +		}
> +	}
> +
> +	used += scnprintf(buf + used, buf_sz - used, "OUT: ");
> +	for (reg_idx = 0;
> +	     reg_idx < drvdata->config.nr_trig_max;
> +	     reg_idx++) {
> +		if (chan_mask & cfg->ctiouten[reg_idx]) {
> +			used += scnprintf(buf + used, buf_sz - used, "%d ",
> +					  reg_idx);
> +		}
> +	}
> +	used += scnprintf(buf + used, buf_sz - used, "\n");
> +	return used;
> +}
> +static DEVICE_ATTR_RW(chan_xtrigs_view);
> +
> +static ssize_t print_chan_list(struct device *dev,
> +			       char *buf, bool inuse)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *config = &drvdata->config;
> +	int size, i;
> +	unsigned long inuse_bits = 0, chan_mask;
> +
> +	/* scan regs to get bitmap of channels in use. */
> +	spin_lock(&drvdata->spinlock);
> +	for (i = 0; i < config->nr_trig_max; i++) {
> +		inuse_bits |= config->ctiinen[i];
> +		inuse_bits |= config->ctiouten[i];
> +	}
> +	spin_unlock(&drvdata->spinlock);
> +
> +	/* inverse bits if printing free channels */
> +	if (!inuse)
> +		inuse_bits = ~inuse_bits;
> +
> +	/* list of channels, or 'none' */
> +	chan_mask = GENMASK(config->nr_ctm_channels - 1, 0);
> +	if (inuse_bits & chan_mask)
> +		size = bitmap_print_to_pagebuf(true, buf, &inuse_bits,
> +					       config->nr_ctm_channels);
> +	else
> +		size = scnprintf(buf, PAGE_SIZE, "\n");
> +	return size;
> +}
> +
> +static ssize_t chan_inuse_show(struct device *dev,
> +			       struct device_attribute *attr,
> +			       char *buf)
> +{
> +	return print_chan_list(dev, buf, true);
> +}
> +static DEVICE_ATTR_RO(chan_inuse);
> +
> +static ssize_t chan_free_show(struct device *dev,
> +			      struct device_attribute *attr,
> +			      char *buf)
> +{
> +	return print_chan_list(dev, buf, false);
> +}
> +static DEVICE_ATTR_RO(chan_free);
> +
> +static struct attribute *coresight_cti_channel_attrs[] = {
> +	&dev_attr_trigin_attach.attr,
> +	&dev_attr_trigin_detach.attr,
> +	&dev_attr_trigout_attach.attr,
> +	&dev_attr_trigout_detach.attr,
> +	&dev_attr_trig_filter_enable.attr,
> +	&dev_attr_trigout_filtered.attr,
> +	&dev_attr_chan_gate_enable.attr,
> +	&dev_attr_chan_gate_disable.attr,
> +	&dev_attr_chan_set.attr,
> +	&dev_attr_chan_clear.attr,
> +	&dev_attr_chan_pulse.attr,
> +	&dev_attr_chan_inuse.attr,
> +	&dev_attr_chan_free.attr,
> +	&dev_attr_chan_xtrigs_view.attr,
> +	&dev_attr_chan_xtrigs_reset.attr,
> +	NULL,
> +};
> +
>  /* sysfs groups */
>  static const struct attribute_group coresight_cti_group = {
>  	.attrs = coresight_cti_attrs,
> @@ -479,9 +822,15 @@ static const struct attribute_group coresight_cti_regs_group = {
>  	.name = "regs",
>  };
>  
> +static const struct attribute_group coresight_cti_channels_group = {
> +	.attrs = coresight_cti_channel_attrs,
> +	.name = "channels",
> +};
> +
>  const struct attribute_group *coresight_cti_groups[] = {
>  	&coresight_cti_group,
>  	&coresight_cti_mgmt_group,
>  	&coresight_cti_regs_group,
> +	&coresight_cti_channels_group,
>  	NULL,
>  };
> diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> index b016b1e67fb1..369488dd7b8e 100644
> --- a/drivers/hwtracing/coresight/coresight-cti.c
> +++ b/drivers/hwtracing/coresight/coresight-cti.c
> @@ -293,6 +293,153 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
>  	return ret;
>  }
>  
> +/** cti channel api **/
> +/* attach/detach channel from trigger - write through if enabled. */
> +int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
> +			enum cti_trig_dir direction, u32 channel_idx,
> +			u32 trigger_idx)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *config = &drvdata->config;
> +	u32 trig_bitmask;
> +	u32 chan_bitmask;
> +	u32 reg_value;
> +	int reg_offset;
> +
> +	/* ensure indexes in range */
> +	if ((channel_idx >= config->nr_ctm_channels) ||
> +	   (trigger_idx >= config->nr_trig_max))
> +		return -EINVAL;
> +
> +	trig_bitmask = BIT(trigger_idx);
> +
> +	/* ensure registered triggers and not out filtered */
> +	if (direction == CTI_TRIG_IN)	{
> +		if (!(trig_bitmask & config->trig_in_use))
> +			return -EINVAL;
> +	} else {
> +		if (!(trig_bitmask & config->trig_out_use))
> +			return -EINVAL;
> +
> +		if ((config->trig_filter_enable) &&
> +		    (config->trig_out_filter & trig_bitmask))
> +			return -EINVAL;
> +	}
> +
> +	/* update the local register values */
> +	chan_bitmask = BIT(channel_idx);
> +	reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
> +		      CTIOUTEN(trigger_idx));
> +
> +	spin_lock(&drvdata->spinlock);
> +
> +	/* read - modify write - the trigger / channel enable value */
> +	reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] :
> +		     config->ctiouten[trigger_idx];
> +	if (op == CTI_CHAN_ATTACH)
> +		reg_value |= chan_bitmask;
> +	else
> +		reg_value &= ~chan_bitmask;
> +
> +	/* write local copy */
> +	if (direction == CTI_TRIG_IN)
> +		config->ctiinen[trigger_idx] = reg_value;
> +	else
> +		config->ctiouten[trigger_idx] = reg_value;
> +
> +	/* write through if enabled */
> +	if (CTI_PWR_ENA(config))
> +		cti_write_single_reg(drvdata, reg_offset, reg_value);
> +	spin_unlock(&drvdata->spinlock);
> +	return 0;
> +}
> +
> +int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
> +			u32 channel_idx)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *config = &drvdata->config;
> +	u32 chan_bitmask;
> +	u32 reg_value;
> +	int err = 0;
> +
> +	if (channel_idx >= config->nr_ctm_channels)
> +		return -EINVAL;
> +
> +	chan_bitmask = BIT(channel_idx);
> +
> +	spin_lock(&drvdata->spinlock);
> +	reg_value = config->ctigate;
> +	switch (op) {
> +	case CTI_GATE_CHAN_ENABLE:
> +		reg_value |= chan_bitmask;
> +		break;
> +
> +	case CTI_GATE_CHAN_DISABLE:
> +		reg_value &= ~chan_bitmask;
> +		break;
> +
> +	default:
> +		err = -EINVAL;
> +		break;
> +	}
> +	if (err == 0) {
> +		config->ctigate = reg_value;
> +		if (CTI_PWR_ENA(config))
> +			cti_write_single_reg(drvdata, CTIGATE, reg_value);
> +	}
> +	spin_unlock(&drvdata->spinlock);
> +	return err;
> +}
> +
> +int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
> +		      u32 channel_idx)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *config = &drvdata->config;
> +	u32 chan_bitmask;
> +	u32 reg_value;
> +	u32 reg_offset;
> +	int err = 0;
> +
> +	if (channel_idx >= config->nr_ctm_channels)
> +		return -EINVAL;
> +
> +	chan_bitmask = BIT(channel_idx);
> +
> +	spin_lock(&drvdata->spinlock);
> +	reg_value = config->ctiappset;
> +	switch (op) {
> +	case CTI_CHAN_SET:
> +		config->ctiappset |= chan_bitmask;
> +		reg_value  = config->ctiappset;
> +		reg_offset = CTIAPPSET;
> +		break;
> +
> +	case CTI_CHAN_CLR:
> +		config->ctiappset &= ~chan_bitmask;
> +		reg_value = chan_bitmask;
> +		reg_offset = CTIAPPCLEAR;
> +		break;
> +
> +	case CTI_CHAN_PULSE:
> +		config->ctiappset &= ~chan_bitmask;
> +		reg_value = chan_bitmask;
> +		reg_offset = CTIAPPPULSE;
> +		break;
> +
> +	default:
> +		err = -EINVAL;
> +		break;
> +	}
> +
> +	if ((err == 0) && CTI_PWR_ENA(config))
> +		cti_write_single_reg(drvdata, reg_offset, reg_value);
> +	spin_unlock(&drvdata->spinlock);
> +
> +	return err;
> +}
> +
>  /** cti ect operations **/
>  int cti_enable(struct coresight_device *csdev)
>  {
> diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
> index 73869fa8b313..9a22f6fcad65 100644
> --- a/drivers/hwtracing/coresight/coresight-cti.h
> +++ b/drivers/hwtracing/coresight/coresight-cti.h
> @@ -168,6 +168,30 @@ struct cti_drvdata {
>  	void (*csdev_release)(struct device *dev);
>  };
>  
> +/*
> + * Channel operation types.
> + */
> +enum cti_chan_op {
> +	CTI_CHAN_ATTACH,
> +	CTI_CHAN_DETACH,
> +};
> +
> +enum cti_trig_dir {
> +	CTI_TRIG_IN,
> +	CTI_TRIG_OUT,
> +};
> +
> +enum cti_chan_gate_op {
> +	CTI_GATE_CHAN_ENABLE,
> +	CTI_GATE_CHAN_DISABLE,
> +};
> +
> +enum cti_chan_set_op {
> +	CTI_CHAN_SET,
> +	CTI_CHAN_CLR,
> +	CTI_CHAN_PULSE,
> +};
> +
>  /* private cti driver fns & vars */
>  extern const struct attribute_group *coresight_cti_groups[];
>  int cti_add_default_connection(struct device *dev,
> @@ -180,8 +204,16 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
>  					   int out_sigs);
>  int cti_enable(struct coresight_device *csdev);
>  int cti_disable(struct coresight_device *csdev);
> +void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
>  void cti_write_intack(struct device *dev, u32 ackval);
>  void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
> +int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
> +			enum cti_trig_dir direction, u32 channel_idx,
> +			u32 trigger_idx);
> +int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
> +			u32 channel_idx);
> +int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
> +		      u32 channel_idx);
>  struct coresight_platform_data *
>  coresight_cti_get_platform_data(struct device *dev);

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

>  
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions.
  2019-11-19 23:19 ` [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions Mike Leach
  2019-11-20 19:06   ` Mathieu Poirier
@ 2019-11-22 23:33   ` Rob Herring
  2019-11-29 13:50     ` Mike Leach
  2019-11-28 18:38   ` Suzuki Kuruppassery Poulose
  2 siblings, 1 reply; 62+ messages in thread
From: Rob Herring @ 2019-11-22 23:33 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc,
	mathieu.poirier, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:03PM +0000, Mike Leach wrote:
> Adds new coresight-cti.yaml file describing the bindings required to define
> CTI in the device trees.
> 
> Adds an include file to dt-bindings/arm to define constants describing
> common signal functionality used in CoreSight and generic usage.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  .../bindings/arm/coresight-cti.yaml           | 303 ++++++++++++++++++
>  .../devicetree/bindings/arm/coresight.txt     |   7 +
>  MAINTAINERS                                   |   2 +
>  include/dt-bindings/arm/coresight-cti-dt.h    |  37 +++
>  4 files changed, 349 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/coresight-cti.yaml
>  create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h
> 
> diff --git a/Documentation/devicetree/bindings/arm/coresight-cti.yaml b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> new file mode 100644
> index 000000000000..882c72f1c798
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> @@ -0,0 +1,303 @@
> +# SPDX-License-Identifier: GPL-2.0

Dual license new bindings please:

(GPL-2.0-only OR BSD-2-Clause)

> +# Copyright 2019 Linaro Ltd.
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/coresight-cti.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: ARM Coresight Cross Trigger Interface (CTI) device.
> +
> +description: |
> +  The CoreSight Embedded Cross Trigger (ECT) consists of CTI devices connected
> +  to one or more CoreSight components and/or a CPU, with CTIs interconnected in
> +  a star topology via the CTM (which is not programmable). The ECT components
> +  are not part of the trace generation data path and are thus not part of the
> +  CoreSight graph described in the general CoreSight bindings file
> +  coresight.txt.
> +
> +  The CTI component properties define the connections between the individual
> +  CTI and the components it is directly connected to, consisting of input and
> +  output hardware trigger signals. CTIs can have a maximum number of input and
> +  output hardware trigger signals (8 each for v1 CTI, 32 each for v2 CTI). The
> +  number is defined at design time, the maximum of each defined in the DEVID
> +  register.
> +
> +  CTIs are interconnected in a star topology via the CTM, using a number of
> +  programmable channels usually 4, but again implementation defined and
> +  described in the DEVID register. The star topology is not required to be
> +  described in the bindings as the actual connections are software
> +  programmable.
> +
> +  In general the connections between CTI and components via the trigger signals
> +  are implementation defined, other than when v8 core and ETM is present.
> +  The v8 architecture defines the required signal connections between CPU core
> +  and CTI, and ETM and CTI, if the ETM if present.
> +
> +  When only minimal information is available for the CTI trigger connections,
> +  then a minimal driver binding can be declare with no explicit trigger
> +  signals. This will result in the using the DEVID register to set the
> +  input and output triggers and channels in use. Any user / client
> +  application will require additional information on the connections
> +  between the CTI and other components for correct operation. This minimal
> +  binding may be used when using the Integration Control registers to
> +  discover connections between CTI and other CoreSight components,
> +
> +  Certain triggers between CoreSight devices and the CTI have specific types
> +  and usages. These can be defined along with the signal indexes with the
> +  constants defined in <dt-bindings/arm/coresight-cti-dt.h>
> +
> +  For example a CTI connected to a core will usually have a DBGREQ signal. This
> +  is defined in the binding as type PE_EDBGREQ. These types will appear in an
> +  optional array alongside the signal indexes. Omitting types will default all
> +  signals to GEN_IO.
> +
> +  Note that some hardware trigger signals can be connected to non-CoreSight
> +  components (e.g. UART etc) depending on hardware implementation.
> +
> +maintainers:
> +  - Mike Leach <mike.leach@linaro.org>
> +
> +allOf:
> +  - $ref: /schemas/arm/primecell.yaml#
> +
> +# Need a custom select here or 'arm,primecell' will match on lots of nodes
> +select:
> +  properties:
> +    compatible:
> +      contains:
> +        enum:
> +          - arm,coresight-cti
> +  required:
> +    - compatible
> +
> +properties:
> +  $nodename:
> +    pattern: "^cti(@[0-9a-f,]+)*$"

Unit address should not be optional nor have a comma.

> +  compatible:
> +    items:
> +      - const: arm,coresight-cti
> +      - const: arm,primecell
> +
> +  reg:
> +    items:
> +      - description: device programming registers

Just "maxItems: 1" is sufficient.

> +
> +  arm,cti-v8-arch:
> +    type: boolean
> +    description:
> +      This CTI follows the v8 architecturally mandated layout for a CTI.

Seems like the compatible or primecell ID registers should be used for 
something like this.

> +      Bindings declaring this must declare a cpu, and optionally a single
> +      arm,cs-dev-assoc may be present to define an attached ETM. No additional
> +      trig-conns nodes are permitted. The driver will build a connection model
> +      according to architectural requirements. This will include a filter on
> +      the CPU dbgreq signal as described above.
> +
> +  cpu:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description: Handle to cpu this device is associated with.
> +
> +  arm,cti-ctm-id:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/uint32
> +    description:
> +      Defines the CTM this CTI is connected to, in large systems with multiple
> +      separate CTI/CTM nets. Typically multi-socket systems where the CTM is
> +      propagated between sockets.
> +
> +  arm,cs-dev-assoc:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description:
> +      defines a phandle reference to an associated CoreSight trace device.

s/defines/Defines/

> +      When the associated trace device is enabled, then the respective CTI
> +      will be enabled. Use in a trig-conns node, or in CTI base node when
> +      arm,cti-v8-arch present. If the associated device has not been registered
> +      then the node name will be stored as the connection name for later
> +      resolution. If the associated device is not a CoreSight device or not
> +      registered then the node name will remain the connection name and
> +      automatic enabling will not occur.
> +
> +patternProperties:
> +  '^trig_conns@[0-9]+$':

trig-conns@...

> +    type: object
> +    description:
> +      A trigger connections child node which describes the trigger signals
> +      between this CTI and another hardware device. This device may be a CPU,
> +      CoreSight device, any other hardware device or simple external IO lines.
> +      The connection may have both input and output triggers, or only one or the
> +      other.
> +
> +    properties:
> +
> +      arm,trig-in-sigs:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of CTI trigger in signal numbers in use by a trig-conns node.
> +
> +      arm,trig-in-types:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of constants representing the types for the CTI trigger in
> +          signals. Types in this array match to the corresponding signal in the
> +          arm,trig-in-sigs array. If the -types array is smaller, or omitted
> +          completely, then the types will default to GEN_IO.
> +
> +      arm,trig-out-sigs:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of CTI trigger out signal numbers in use by a trig-conns node.
> +
> +      arm,trig-out-types:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of constants representing the types for the CTI trigger out
> +          signals. Types in this array match to the corresponding signal
> +          in the arm,trig-out-sigs array. If the "-types" array is smaller,
> +          or omitted completely, then the types will default to GEN_IO.
> +
> +      arm,trig-filters:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of CTI trigger out signals that will be blocked from becoming
> +          active, unless filtering is disabled on the driver.
> +
> +      arm,trig-conn-name:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/string
> +        description:
> +          Defines a connection name that will be displayed, if the cpu or
> +          arm,cs-dev-assoc properties are not being used in this connection.
> +          Principle use for CTI that are connected to non-CoreSight devices, or
> +          external IO.
> +
> +    anyOf:
> +      - required:
> +        - arm,trig-in-sigs
> +      - required:
> +        - arm,trig-out-sigs
> +    oneOf:
> +      - required:
> +        - arm,trig-conn-name
> +      - required:
> +        - cpu
> +      - required:
> +        - arm,cs-dev-assoc
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - clock-names
> +
> +examples:
> +  # minimum CTI definition. DEVID register used to set number of triggers.
> +  - |
> +    cti@20020000 {
> +      compatible = "arm,coresight-cti", "arm,primecell";
> +      reg = <0x20020000 0x1000>;
> +
> +      clocks = <&soc_smc50mhz>;
> +      clock-names = "apb_pclk";
> +    };
> +  #  v8 architecturally defined CTI - CPU + ETM connections generated by the
> +  #  driver according to the v8 architecture specification.
> +  - |
> +    cti@859000 {
> +      compatible = "arm,coresight-cti", "arm,primecell";
> +      reg = <0x859000 0x1000>;
> +
> +      clocks = <&soc_smc50mhz>;
> +      clock-names = "apb_pclk";
> +
> +      arm,cti-v8-arch;
> +      cpu = <&CPU1>;
> +      arm,cs-dev-assoc = <&etm1>;
> +    };
> +  # Implementation defined CTI - CPU + ETM connections explicitly defined..
> +  # Shows use of type constants from dt-bindings/arm/coresight-cti-dt.h
> +  - |
> +    #include <dt-bindings/arm/coresight-cti-dt.h>
> +
> +    cti@858000 {
> +      compatible = "arm,coresight-cti", "arm,primecell";
> +      reg = <0x858000 0x1000>;
> +
> +      clocks = <&soc_smc50mhz>;
> +      clock-names = "apb_pclk";
> +
> +      arm,cti-ctm-id = <1>;
> +
> +      trig-conns@0 {
> +            arm,trig-in-sigs = <4 5 6 7>;
> +            arm,trig-in-types = <ETM_EXTOUT
> +                                 ETM_EXTOUT
> +                                 ETM_EXTOUT
> +                                 ETM_EXTOUT>;
> +            arm,trig-out-sigs = <4 5 6 7>;
> +            arm,trig-out-types = <ETM_EXTIN
> +                                  ETM_EXTIN
> +                                  ETM_EXTIN
> +                                  ETM_EXTIN>;
> +            arm,cs-dev-assoc = <&etm0>;
> +      };
> +
> +      trig-conns@1 {
> +            cpu = <&CPU0>;
> +            arm,trig-in-sigs = <0 1>;
> +            arm,trig-in-types = <PE_DBGTRIGGER
> +                                 PE_PMUIRQ>;
> +            arm,trig-out-sigs=<0 1 2 >;
> +            arm,trig-out-types = <PE_EDBGREQ
> +                                  PE_DBGRESTART
> +                                  PE_CTIIRQ>;
> +
> +            arm,trig-filters = <0>;
> +      };
> +    };
> +  # Implementation defined CTI - none CoreSight component connections.
> +  - |
> +    cti@20110000 {
> +      compatible = "arm,coresight-cti", "arm,primecell";
> +      reg = <0 0x20110000 0 0x1000>;
> +
> +      clocks = <&soc_smc50mhz>;
> +      clock-names = "apb_pclk";
> +
> +      trig-conns@0 {
> +        arm,trig-in-sigs=<0>;
> +        arm,trig-in-types=<GEN_INTREQ>;
> +        arm,trig-out-sigs=<0>;
> +        arm,trig-out-types=<GEN_HALTREQ>;
> +        arm,trig-conn-name = "sys_profiler";
> +      };
> +
> +      trig-conns@1 {
> +        arm,trig-out-sigs=<2 3>;
> +        arm,trig-out-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> +        arm,trig-conn-name = "watchdog";
> +      };
> +
> +      trig-conns@2 {
> +        arm,trig-in-sigs=<1 6>;
> +        arm,trig-in-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> +        arm,trig-conn-name = "g_counter";
> +      };
> +    };
> +
> +...
> \ No newline at end of file

'...' is preferred, but the fix the lack of newline.

> diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
> index d02c42d21f2f..846f6daae71b 100644
> --- a/Documentation/devicetree/bindings/arm/coresight.txt
> +++ b/Documentation/devicetree/bindings/arm/coresight.txt
> @@ -45,6 +45,10 @@ its hardware characteristcs.
>  		- Coresight Address Translation Unit (CATU)
>  			"arm,coresight-catu", "arm,primecell";
>  
> +		- Coresight Cross Trigger Interface (CTI):
> +			"arm,coresight-cti", "arm,primecell";
> +			See coresight-cti.yaml for full CTI definitions.
> +
>  	* reg: physical base address and length of the register
>  	  set(s) of the component.
>  
> @@ -72,6 +76,9 @@ its hardware characteristcs.
>  	* reg-names: the only acceptable values are "stm-base" and
>  	  "stm-stimulus-base", each corresponding to the areas defined in "reg".
>  
> +* Required properties for Coresight Cross Trigger Interface (CTI)
> +	See coresight-cti.yaml for full CTI definitions.
> +
>  * Required properties for devices that don't show up on the AMBA bus, such as
>    non-configurable replicators and non-configurable funnels:
>  
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9de89d75dbcc..8d01a74068f7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1608,9 +1608,11 @@ R:	Suzuki K Poulose <suzuki.poulose@arm.com>
>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
>  S:	Maintained
>  F:	drivers/hwtracing/coresight/*
> +F:	include/dt-bindings/arm/coresight-cti-dt.h
>  F:	Documentation/trace/coresight/*
>  F:	Documentation/devicetree/bindings/arm/coresight.txt
>  F:	Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt
> +F:	Documentation/devicetree/bindings/arm/coresight-cti.yaml
>  F:	Documentation/ABI/testing/sysfs-bus-coresight-devices-*
>  F:	tools/perf/arch/arm/util/pmu.c
>  F:	tools/perf/arch/arm/util/auxtrace.c
> diff --git a/include/dt-bindings/arm/coresight-cti-dt.h b/include/dt-bindings/arm/coresight-cti-dt.h
> new file mode 100644
> index 000000000000..61e7bdf8ea6e
> --- /dev/null
> +++ b/include/dt-bindings/arm/coresight-cti-dt.h
> @@ -0,0 +1,37 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * This header provides constants for the defined trigger signal
> + * types on CoreSight CTI.
> + */
> +
> +#ifndef _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
> +#define _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
> +
> +#define GEN_IO		0
> +#define GEN_INTREQ	1
> +#define GEN_INTACK	2
> +#define GEN_HALTREQ	3
> +#define GEN_RESTARTREQ	4
> +#define PE_EDBGREQ	5
> +#define PE_DBGRESTART	6
> +#define PE_CTIIRQ	7
> +#define PE_PMUIRQ	8
> +#define PE_DBGTRIGGER	9
> +#define ETM_EXTOUT	10
> +#define ETM_EXTIN	11
> +#define SNK_FULL	12
> +#define SNK_ACQCOMP	13
> +#define SNK_FLUSHCOMP	14
> +#define SNK_FLUSHIN	15
> +#define SNK_TRIGIN	16
> +#define STM_ASYNCOUT	17
> +#define STM_TOUT_SPTE	18
> +#define STM_TOUT_SW	19
> +#define STM_TOUT_HETE	20
> +#define STM_HWEVENT	21
> +#define ELA_TSTART	22
> +#define ELA_TSTOP	23
> +#define ELA_DBGREQ	24
> +#define CTI_TRIG_MAX	25
> +
> +#endif /*_DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H */
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI
  2019-11-19 23:19 ` [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI Mike Leach
@ 2019-11-25 19:00   ` Mathieu Poirier
  2019-11-29 11:33   ` Suzuki Kuruppassery Poulose
  1 sibling, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-25 19:00 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:04PM +0000, Mike Leach wrote:
> The v8 architecture defines the relationship between a PE, its optional ETM
> and a CTI. Unlike non-architectural CTIs which are implementation defined,
> this has a fixed set of connections which can therefore be represented as a
> simple tag in the device tree.
> 
> This patch defines the tags needed to create an entry for this PE/ETM/CTI
> relationship, and provides functionality to implement the connection model
> in the CTI driver.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  .../coresight/coresight-cti-platform.c        | 205 ++++++++++++++++++
>  1 file changed, 205 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
> index 665be86c585d..790dd30b85f5 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-platform.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
> @@ -3,10 +3,208 @@
>   * Copyright (c) 2019, The Linaro Limited. All rights reserved.
>   */
>  
> +#include <dt-bindings/arm/coresight-cti-dt.h>
>  #include <linux/of.h>
>  
>  #include "coresight-cti.h"
>  
> +/* Number of CTI signals in the v8 architecturally defined connection */
> +#define NR_V8PE_IN_SIGS		2
> +#define NR_V8PE_OUT_SIGS	3
> +#define NR_V8ETM_INOUT_SIGS	4
> +
> +/* CTI device tree connection property keywords */
> +#define CTI_DT_V8ARCH		"arm,cti-v8-arch"
> +#define CTI_DT_CSDEV_ASSOC	"arm,cs-dev-assoc"
> +
> +/*
> + * Find a registered coresight device from a device fwnode.
> + * The node info is associated with the AMBA parent, but the
> + * csdev keeps a copy so iterate round the coresight bus to
> + * find the device.
> + */
> +static struct coresight_device *
> +cti_get_assoc_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
> +{
> +	struct device *dev;
> +	struct coresight_device *csdev = NULL;
> +
> +	dev = bus_find_device_by_fwnode(&coresight_bustype, r_fwnode);
> +	if (dev) {
> +		csdev = to_coresight_device(dev);
> +		put_device(dev);
> +	}
> +	return csdev;
> +}
> +
> +#ifdef CONFIG_OF
> +/*
> + * CTI can be bound to a CPU, or a system device.
> + * CPU can be declared at the device top level or in a connections node
> + * so need to check relative to node not device.
> + */
> +static int of_cti_get_cpu_at_node(const struct device_node *node)
> +{
> +	int cpu;
> +	struct device_node *dn;
> +
> +	if (node == NULL)
> +		return -1;
> +
> +	dn = of_parse_phandle(node, "cpu", 0);
> +	/* CTI affinity defaults to no cpu */
> +	if (!dn)
> +		return -1;
> +	cpu = of_cpu_node_to_id(dn);
> +	of_node_put(dn);
> +
> +	/* No Affinity  if no cpu nodes are found */
> +	return (cpu < 0) ? -1 : cpu;
> +}
> +
> +static const char *of_cti_get_node_name(const struct device_node *node)
> +{
> +	if (node)
> +		return node->full_name;
> +	return "unknown";
> +}
> +#else
> +static int of_cti_get_cpu_at_node(const struct device_node *node)
> +{
> +	return -1;
> +}
> +
> +static const char *of_cti_get_node_name(const struct device_node *node)
> +{
> +	return "unknown";
> +}
> +#endif
> +
> +static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
> +{
> +	if (is_of_node(fwnode))
> +		return of_cti_get_cpu_at_node(to_of_node(fwnode));
> +	return -1;
> +}
> +
> +static const char *cti_plat_get_node_name(struct fwnode_handle *fwnode)
> +{
> +	if (is_of_node(fwnode))
> +		return of_cti_get_node_name(to_of_node(fwnode));
> +	return "unknown";
> +}
> +
> +static int cti_plat_create_v8_etm_connection(struct device *dev,
> +					     struct cti_drvdata *drvdata)
> +{
> +	int ret = -ENOMEM, i;
> +	struct fwnode_handle *root_fwnode, *cs_fwnode;
> +	const char *assoc_name = NULL;
> +	struct coresight_device *csdev;
> +	struct cti_trig_con *tc = NULL;
> +
> +	root_fwnode = dev_fwnode(dev);
> +	if (IS_ERR_OR_NULL(root_fwnode))
> +		return -EINVAL;
> +
> +	/* Can optionally have an etm node - return if not  */
> +	cs_fwnode = fwnode_find_reference(root_fwnode, CTI_DT_CSDEV_ASSOC, 0);
> +	if (IS_ERR_OR_NULL(cs_fwnode))
> +		return 0;
> +
> +	/* allocate memory */
> +	tc = cti_allocate_trig_con(dev, NR_V8ETM_INOUT_SIGS,
> +				   NR_V8ETM_INOUT_SIGS);
> +	if (!tc)
> +		goto create_v8_etm_out;
> +
> +	/* build connection data */
> +	tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */
> +	tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */
> +
> +	/*
> +	 * The EXTOUT type signals from the ETM are connected to a set of input
> +	 * triggers on the CTI, the EXTIN being connected to output triggers.
> +	 */
> +	for (i = 0; i < NR_V8ETM_INOUT_SIGS; i++) {
> +		tc->con_in->sig_types[i] = ETM_EXTOUT;
> +		tc->con_out->sig_types[i] = ETM_EXTIN;
> +	}
> +
> +	/*
> +	 * We look to see if the ETM coresight device associated with this
> +	 * handle has been registered with the system - i.e. probed before
> +	 * this CTI. If so csdev will be non NULL and we can use the device
> +	 * name and pass the csdev to the connection entry function where
> +	 * the association will be recorded.
> +	 * If not, then simply record the name in the connection data, the
> +	 * probing of the ETM will call into the CTI driver API to update the
> +	 * association then.
> +	 */
> +	csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
> +	if (csdev)
> +		assoc_name = dev_name(&csdev->dev);
> +	else
> +		assoc_name = cti_plat_get_node_name(cs_fwnode);
> +	ret = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name);
> +
> +create_v8_etm_out:
> +	fwnode_handle_put(cs_fwnode);
> +	return ret;
> +}
> +
> +/*
> + * Create an architecturally defined v8 connection
> + * must have a cpu, can have an ETM.
> + */
> +static int cti_plat_create_v8_connections(struct device *dev,
> +					  struct cti_drvdata *drvdata)
> +{
> +	struct cti_device *cti_dev = &drvdata->ctidev;
> +	struct cti_trig_con *tc = NULL;
> +	int cpuid = 0;
> +	char cpu_name_str[16];
> +	int ret = -ENOMEM;
> +
> +	/* Must have a cpu node */
> +	cpuid = cti_plat_get_cpu_at_node(dev_fwnode(dev));
> +	if (cpuid < 0) {
> +		dev_warn(dev, "CTI v8 DT binding no cpu\n");
> +		return -EINVAL;
> +	}
> +	cti_dev->cpu = cpuid;
> +
> +	/* Allocate the v8 cpu connection memory */
> +	tc = cti_allocate_trig_con(dev, NR_V8PE_IN_SIGS, NR_V8PE_OUT_SIGS);
> +	if (!tc)
> +		goto of_create_v8_out;
> +
> +	/* Set the v8 PE CTI connection data */
> +	tc->con_in->used_mask = 0x3; /* sigs <0 1> */
> +	tc->con_in->sig_types[0] = PE_DBGTRIGGER;
> +	tc->con_in->sig_types[1] = PE_PMUIRQ;
> +	tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */
> +	tc->con_out->sig_types[0] = PE_EDBGREQ;
> +	tc->con_out->sig_types[1] = PE_DBGRESTART;
> +	tc->con_out->sig_types[2] = PE_CTIIRQ;
> +	scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid);
> +
> +	ret = cti_add_connection_entry(dev, drvdata, tc, NULL, cpu_name_str);
> +	if (ret)
> +		goto of_create_v8_out;
> +
> +	/* Create the v8 ETM associated connection */
> +	ret = cti_plat_create_v8_etm_connection(dev, drvdata);
> +	if (ret)
> +		goto of_create_v8_out;
> +
> +	/* filter pe_edbgreq - PE trigout sig <0> */
> +	drvdata->config.trig_out_filter |= 0x1;
> +
> +of_create_v8_out:
> +	return ret;
> +}
> +
>  /* get the hardware configuration & connection data. */
>  int cti_plat_get_hw_data(struct device *dev,
>  			 struct cti_drvdata *drvdata)
> @@ -14,6 +212,13 @@ int cti_plat_get_hw_data(struct device *dev,
>  	int rc = 0;
>  	struct cti_device *cti_dev = &drvdata->ctidev;
>  
> +	/* check for a v8 architectural CTI device */
> +	if (device_property_read_bool(dev, CTI_DT_V8ARCH)) {
> +		rc = cti_plat_create_v8_connections(dev, drvdata);
> +		if (rc)
> +			return rc;
> +	}
> +
>  	/* if no connections, just add a single default based on max IN-OUT */
>  	if (cti_dev->nr_trig_con == 0)
>  		rc = cti_add_default_connection(dev, drvdata);

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 01/14] coresight: cti: Initial CoreSight CTI Driver
  2019-11-19 23:18 ` [PATCH v5 01/14] coresight: cti: Initial " Mike Leach
  2019-11-21 20:21   ` Mathieu Poirier
@ 2019-11-25 19:03   ` Suzuki Kuruppassery Poulose
  2019-11-29 12:06     ` Mike Leach
  1 sibling, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-25 19:03 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

On 19/11/2019 23:18, Mike Leach wrote:
> This introduces a baseline CTI driver and associated configuration files.
> 
> Uses the platform agnostic naming standard for CoreSight devices, along
> with a generic platform probing method that currently supports device
> tree descriptions, but allows for the ACPI bindings to be added once these
> have been defined for the CTI devices.
> 
> Driver will probe for the device on the AMBA bus, and load the CTI driver
> on CoreSight ID match to CTI IDs in tables.
> 
> Initial sysfs support for enable / disable provided.
> 
> Default CTI interconnection data is generated based on hardware
> register signal counts, with no additional connection information.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>

Looks good to me.  Some very minor nits, feel free to ignore if you are 
not respinning the series.

> +/*
> + * Look at the HW DEVID register for some of the HW settings.
> + * DEVID[15:8] - max number of in / out triggers.
> + */
> +#define CTI_DEVID_MAXTRIGS(devid_val) (int)((devid_val & 0xFF00) >> 8)

BMVAL(devid_val, 15, 8)

> +
> +/* DEVID[19:16] - number of CTM channels */
> +#define CTI_DEVID_CTMCHANNELS(devid_val) (int)((devid_val & 0xF0000) >> 16)

BMVAL(devid_val, 19, 16)

> +
> +static void cti_set_default_config(struct device *dev,
> +				   struct cti_drvdata *drvdata)
> +{
> +	struct cti_config *config = &drvdata->config;
> +	u32 devid;
> +
> +	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
> +	config->nr_trig_max = CTI_DEVID_MAXTRIGS(devid);
> +
> +	/*
> +	 * no current hardware should exceed this, but protect the driver
> +	 * in case of fault / out of spec hw
> +	 */
> +	if (config->nr_trig_max > CTIINOUTEN_MAX) {
> +		dev_warn_once(dev,
> +			"Limiting HW MaxTrig value(%d) to driver max(%d)\n",
> +			config->nr_trig_max, CTIINOUTEN_MAX);
> +		config->nr_trig_max = CTIINOUTEN_MAX;
> +	}
> +
> +	config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid);
> +
> +	/* Most regs default to 0 as zalloc'ed except...*/
> +	config->trig_filter_enable = true;
> +	config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
> +	atomic_set(&config->enable_req_count, 0);
> +}
> +
> +/*
> + * Add a connection entry to the list of connections for this
> + * CTI device.
> + */
> +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
> +			     struct cti_trig_con *tc,
> +			     struct coresight_device *csdev,
> +			     const char *assoc_dev_name)
> +{
> +	struct cti_device *cti_dev = &drvdata->ctidev;
> +
> +	tc->con_dev = csdev;
> +	/*
> +	 * Prefer actual associated CS device dev name to supplied value -
> +	 * which is likely to be node name / other conn name.
> +	 */
> +	if (csdev)
> +		tc->con_dev_name = devm_kstrdup(dev,
> +						dev_name(&csdev->dev),
> +						GFP_KERNEL);
> +	else if (assoc_dev_name != NULL)
> +		tc->con_dev_name = devm_kstrdup(dev,
> +						assoc_dev_name, GFP_KERNEL);
> +	list_add_tail(&tc->node, &cti_dev->trig_cons);
> +	cti_dev->nr_trig_con++;
> +
> +	/* add connection usage bit info to overall info */
> +	drvdata->config.trig_in_use |= tc->con_in->used_mask;
> +	drvdata->config.trig_out_use |= tc->con_out->used_mask;

Do we need to make sure that they are exclusive ?

  WARN_ON(drvdata->config.trig_in_use ^ ~(tc->con_in->used_mask));
  WARN_ON(drvdata->config.trig_out_use ^ ~(tc->con_out->used_mask));

> +/** cti ect operations **/
> +int cti_enable(struct coresight_device *csdev)
> +{
> +	struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> +
> +	/* enable hardware with refcount */

nit: left over comment from previous revision ?

> +	return cti_enable_hw(drvdata);
> +}
> +
> +int cti_disable(struct coresight_device *csdev)
> +{
> +	struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> +
> +	/* disable hardware with refcount */

same here ?

> +	return cti_disable_hw(drvdata);
> +}
> +

> +
> +static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> +{
> +	int ret = 0;
> +	void __iomem *base;
> +	struct device *dev = &adev->dev;
> +	struct cti_drvdata *drvdata = NULL;
> +	struct coresight_desc cti_desc;
> +	struct coresight_platform_data *pdata = NULL;
> +	struct resource *res = &adev->res;
> +
> +	/* driver data*/
> +	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> +	if (!drvdata) {
> +		ret = -ENOMEM;
> +		dev_info(dev, "%s, mem err\n", __func__);

dev_err() ? As they may have higher priority than "info" and will get
displayed in the rare chance of them getting hit.

> +		goto err_out;
> +	}
> +
> +	/* Validity for the resource is already checked by the AMBA core */
> +	base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(base)) {
> +		ret = PTR_ERR(base);
> +		dev_info(dev, "%s, remap err\n", __func__);

same here, dev_err()

> +		goto err_out;
> +	}
> +	drvdata->base = base;
> +
> +	dev_set_drvdata(dev, drvdata);
> +
> +	/* default CTI device info  */
> +	drvdata->ctidev.cpu = -1;
> +	drvdata->ctidev.nr_trig_con = 0;
> +	drvdata->ctidev.ctm_id = 0;
> +	INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);
> +
> +	spin_lock_init(&drvdata->spinlock);
> +
> +	/* initialise CTI driver config values */
> +	cti_set_default_config(dev, drvdata);
> +
> +	/* Parse the .dts for connections and signals */

minor nit: I would not mention about ".dts" here. The function name is
implicit. You could actually remove that comment.

As mentioned above, the comments are minor nits. So you may add
with/without addressing them:

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI.
  2019-11-19 23:19 ` [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI Mike Leach
@ 2019-11-25 21:22   ` Mathieu Poirier
  2019-11-29 14:16     ` Suzuki Kuruppassery Poulose
  2019-11-29 14:18   ` Suzuki Kuruppassery Poulose
  1 sibling, 1 reply; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-25 21:22 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:05PM +0000, Mike Leach wrote:
> Adds support for CTIs whose connections are implementation defined at
> hardware design time, and not constrained by v8 architecture.
> 
> These CTIs have no standard connection setup, all the settings have to
> be defined in the device tree files. The patch creates a set of connections
> and trigger signals based on the information provided.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  .../coresight/coresight-cti-platform.c        | 250 +++++++++++++++++-
>  .../hwtracing/coresight/coresight-cti-sysfs.c |  11 +
>  2 files changed, 257 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
> index 790dd30b85f5..9c1ff432b487 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-platform.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
> @@ -13,9 +13,19 @@
>  #define NR_V8PE_OUT_SIGS	3
>  #define NR_V8ETM_INOUT_SIGS	4
>  
> +/* CTI device tree trigger connection node keyword */
> +#define CTI_DT_CONNS		"trig-conns"
> +
>  /* CTI device tree connection property keywords */
>  #define CTI_DT_V8ARCH		"arm,cti-v8-arch"
>  #define CTI_DT_CSDEV_ASSOC	"arm,cs-dev-assoc"
> +#define CTI_DT_TRIGIN_SIGS	"arm,trig-in-sigs"
> +#define CTI_DT_TRIGOUT_SIGS	"arm,trig-out-sigs"
> +#define CTI_DT_TRIGIN_TYPES	"arm,trig-in-types"
> +#define CTI_DT_TRIGOUT_TYPES	"arm,trig-out-types"
> +#define CTI_DT_FILTER_OUT_SIGS	"arm,trig-filters"
> +#define CTI_DT_CONN_NAME	"arm,trig-conn-name"
> +#define CTI_DT_CTM_ID		"arm,cti-ctm-id"
>  
>  /*
>   * Find a registered coresight device from a device fwnode.
> @@ -68,6 +78,12 @@ static const char *of_cti_get_node_name(const struct device_node *node)
>  		return node->full_name;
>  	return "unknown";
>  }
> +
> +static bool of_cti_node_name_eq(const struct device_node *node,
> +				const char *name)
> +{
> +	return of_node_name_eq(node, name);
> +}
>  #else
>  static int of_cti_get_cpu_at_node(const struct device_node *node)
>  {
> @@ -78,6 +94,12 @@ static const char *of_cti_get_node_name(const struct device_node *node)
>  {
>  	return "unknown";
>  }
> +
> +static bool of_cti_node_name_eq(const struct device_node *node,
> +				const char *name)
> +{
> +	return false;
> +}
>  #endif
>  
>  static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
> @@ -94,6 +116,14 @@ static const char *cti_plat_get_node_name(struct fwnode_handle *fwnode)
>  	return "unknown";
>  }
>  
> +static bool cti_plat_node_name_eq(struct fwnode_handle *fwnode,
> +				  const char *name)
> +{
> +	if (is_of_node(fwnode))
> +		return of_cti_node_name_eq(to_of_node(fwnode), name);
> +	return false;
> +}
> +
>  static int cti_plat_create_v8_etm_connection(struct device *dev,
>  					     struct cti_drvdata *drvdata)
>  {
> @@ -205,6 +235,214 @@ static int cti_plat_create_v8_connections(struct device *dev,
>  	return ret;
>  }
>  
> +static int cti_plat_count_sig_elements(const struct fwnode_handle *fwnode,
> +				       const char *name)
> +{
> +	int nr_elem = fwnode_property_count_u32(fwnode, name);
> +
> +	return (nr_elem < 0 ? 0 : nr_elem);
> +}
> +
> +static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp,
> +				    const struct fwnode_handle *fwnode,
> +				    const char *grp_name)
> +{
> +	int idx, err = 0;
> +	u32 *values;
> +
> +	if (!tgrp->nr_sigs)
> +		return 0;
> +
> +	values = kcalloc(tgrp->nr_sigs, sizeof(u32), GFP_KERNEL);
> +	if (!values)
> +		return -ENOMEM;
> +
> +	err = fwnode_property_read_u32_array(fwnode, grp_name,
> +					     values, tgrp->nr_sigs);
> +
> +	if (!err) {
> +		/* set the signal usage mask */
> +		for (idx = 0; idx < tgrp->nr_sigs; idx++)
> +			tgrp->used_mask |= BIT(values[idx]);
> +	}
> +
> +	kfree(values);
> +	return err;
> +}
> +
> +static int cti_plat_read_trig_types(struct cti_trig_grp *tgrp,
> +				    const struct fwnode_handle *fwnode,
> +				    const char *type_name)
> +{
> +	int items, used = 0, err = 0, nr_sigs;
> +	u32 *values = NULL, i;
> +
> +	/* allocate an array according to number of signals in connection */
> +	nr_sigs = tgrp->nr_sigs;
> +	if (!nr_sigs)
> +		return 0;
> +
> +	/* see if any types have been included in the device description */
> +	items = cti_plat_count_sig_elements(fwnode, type_name);
> +	if (items > nr_sigs)
> +		return -EINVAL;
> +
> +	/* need an array to store the values iff there are any */
> +	if (items) {
> +		values = kcalloc(items, sizeof(u32), GFP_KERNEL);
> +		if (!values)
> +			return -ENOMEM;
> +
> +		err = fwnode_property_read_u32_array(fwnode, type_name,
> +						     values, items);
> +		if (err)
> +			goto read_trig_types_out;
> +	}
> +
> +	/*
> +	 * Match type id to signal index, 1st type to 1st index etc.
> +	 * If fewer types than signals default remainder to GEN_IO.
> +	 */
> +	for (i = 0; i < nr_sigs; i++) {
> +		if (used < items) {
> +			tgrp->sig_types[i] =
> +				values[i] < CTI_TRIG_MAX ? values[i] : GEN_IO;
> +			used++;
> +		} else {
> +			tgrp->sig_types[i] = GEN_IO;
> +		}
> +	}
> +
> +read_trig_types_out:
> +	kfree(values);
> +	return err;
> +}
> +
> +static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata,
> +					const struct fwnode_handle *fwnode)
> +{
> +	struct cti_trig_grp *tg = NULL;
> +	int err = 0, nr_filter_sigs;
> +
> +	nr_filter_sigs = cti_plat_count_sig_elements(fwnode,
> +						     CTI_DT_FILTER_OUT_SIGS);
> +	if (nr_filter_sigs == 0)
> +		return 0;
> +
> +	if (nr_filter_sigs > drvdata->config.nr_trig_max)
> +		return -EINVAL;
> +
> +	tg = kzalloc(sizeof(*tg), GFP_KERNEL);
> +	if (!tg)
> +		return -ENOMEM;
> +
> +	err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS);
> +	if (!err)
> +		drvdata->config.trig_out_filter |= tg->used_mask;
> +
> +	kfree(tg);
> +	return err;
> +}
> +
> +static int cti_plat_create_connection(struct device *dev,
> +				      struct cti_drvdata *drvdata,
> +				      struct fwnode_handle *fwnode)
> +{
> +	struct cti_trig_con *tc = NULL;
> +	int cpuid = -1, err = 0;
> +	struct fwnode_handle *cs_fwnode = NULL;
> +	struct coresight_device *csdev = NULL;
> +	const char *assoc_name = "unknown";
> +	char cpu_name_str[16];
> +	int nr_sigs_in, nr_sigs_out;
> +
> +	/* look to see how many in and out signals we have */
> +	nr_sigs_in = cti_plat_count_sig_elements(fwnode, CTI_DT_TRIGIN_SIGS);
> +	nr_sigs_out = cti_plat_count_sig_elements(fwnode, CTI_DT_TRIGOUT_SIGS);
> +
> +	if ((nr_sigs_in > drvdata->config.nr_trig_max) ||
> +	    (nr_sigs_out > drvdata->config.nr_trig_max))
> +		return -EINVAL;
> +
> +	tc = cti_allocate_trig_con(dev, nr_sigs_in, nr_sigs_out);
> +	if (!tc)
> +		return -ENOMEM;
> +
> +	/* look for the signals properties. */
> +	err = cti_plat_read_trig_group(tc->con_in, fwnode,
> +				       CTI_DT_TRIGIN_SIGS);
> +	if (err)
> +		goto create_con_err;
> +
> +	err = cti_plat_read_trig_types(tc->con_in, fwnode,
> +				       CTI_DT_TRIGIN_TYPES);
> +	if (err)
> +		goto create_con_err;
> +
> +	err = cti_plat_read_trig_group(tc->con_out, fwnode,
> +				       CTI_DT_TRIGOUT_SIGS);
> +	if (err)
> +		goto create_con_err;
> +
> +	err = cti_plat_read_trig_types(tc->con_out, fwnode,
> +				       CTI_DT_TRIGOUT_TYPES);
> +	if (err)
> +		goto create_con_err;
> +
> +	err = cti_plat_process_filter_sigs(drvdata, fwnode);
> +	if (err)
> +		goto create_con_err;
> +
> +	/* read the connection name if set - may be overridden by later */
> +	fwnode_property_read_string(fwnode, CTI_DT_CONN_NAME, &assoc_name);
> +
> +	/* associated cpu ? */
> +	cpuid = cti_plat_get_cpu_at_node(fwnode);
> +	if (cpuid >= 0) {
> +		drvdata->ctidev.cpu = cpuid;
> +		scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid);
> +		assoc_name = cpu_name_str;
> +	} else {
> +		/* associated device ? */
> +		cs_fwnode = fwnode_find_reference(fwnode,
> +						  CTI_DT_CSDEV_ASSOC, 0);
> +		if (!IS_ERR_OR_NULL(cs_fwnode)) {
> +			csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
> +			if (csdev) /* use device name if csdev found */
> +				assoc_name = dev_name(&csdev->dev);
> +			else  /* otherwise node name for later association */
> +				assoc_name = cti_plat_get_node_name(cs_fwnode);
> +			fwnode_handle_put(cs_fwnode);
> +		}
> +	}
> +	/* set up a connection */
> +	err = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name);
> +
> +create_con_err:
> +	return err;
> +}
> +
> +static int cti_plat_create_impdef_connections(struct device *dev,
> +					      struct cti_drvdata *drvdata)
> +{
> +	int rc = 0;
> +	struct fwnode_handle *fwnode = dev_fwnode(dev);
> +	struct fwnode_handle *child = NULL;
> +
> +	if (IS_ERR_OR_NULL(fwnode))
> +		return -EINVAL;
> +
> +	fwnode_for_each_child_node(fwnode, child) {
> +		if (cti_plat_node_name_eq(child, CTI_DT_CONNS))
> +			rc = cti_plat_create_connection(dev, drvdata, child);
> +		if (rc != 0)
> +			break;
> +	}
> +	fwnode_handle_put(child);

As far as I can tell we don't need to call fwnode_handle_put()?

With the above:
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

> +
> +	return rc;
> +}
> +
>  /* get the hardware configuration & connection data. */
>  int cti_plat_get_hw_data(struct device *dev,
>  			 struct cti_drvdata *drvdata)
> @@ -212,12 +450,16 @@ int cti_plat_get_hw_data(struct device *dev,
>  	int rc = 0;
>  	struct cti_device *cti_dev = &drvdata->ctidev;
>  
> +	/* get any CTM ID - defaults to 0 */
> +	device_property_read_u32(dev, CTI_DT_CTM_ID, &cti_dev->ctm_id);
> +
>  	/* check for a v8 architectural CTI device */
> -	if (device_property_read_bool(dev, CTI_DT_V8ARCH)) {
> +	if (device_property_read_bool(dev, CTI_DT_V8ARCH))
>  		rc = cti_plat_create_v8_connections(dev, drvdata);
> -		if (rc)
> -			return rc;
> -	}
> +	else
> +		rc = cti_plat_create_impdef_connections(dev, drvdata);
> +	if (rc)
> +		return rc;
>  
>  	/* if no connections, just add a single default based on max IN-OUT */
>  	if (cti_dev->nr_trig_con == 0)
> diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> index 98de8a4768fc..f800402f73da 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> @@ -56,9 +56,20 @@ static ssize_t enable_store(struct device *dev,
>  }
>  static DEVICE_ATTR_RW(enable);
>  
> +static ssize_t ctmid_show(struct device *dev,
> +			  struct device_attribute *attr,
> +			  char *buf)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +
> +	return scnprintf(buf, PAGE_SIZE, "%d\n", drvdata->ctidev.ctm_id);
> +}
> +static DEVICE_ATTR_RO(ctmid);
> +
>  /* attribute and group sysfs tables. */
>  static struct attribute *coresight_cti_attrs[] = {
>  	&dev_attr_enable.attr,
> +	&dev_attr_ctmid.attr,
>  	NULL,
>  };
>  
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices.
  2019-11-19 23:19 ` [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices Mike Leach
@ 2019-11-25 22:45   ` Mathieu Poirier
  2019-12-05 16:33     ` Mike Leach
  2019-11-29 18:28   ` Suzuki Kuruppassery Poulose
  1 sibling, 1 reply; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-25 22:45 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:06PM +0000, Mike Leach wrote:
> The CoreSight subsystem enables a path of devices from source to sink.
> Any CTI devices associated with the path devices must be enabled at the
> same time.
> 
> This patch adds an associated coresight_device element to the main
> coresight device structure, and uses this to create associations between
> the CTI and other devices based on the device tree data. The associated
> device element is used to enable CTI in conjunction with the path elements.
> 
> CTI devices are reference counted so where a single CTI is associated with
> multiple elements on the path, it will be enabled on the first associated
> device enable, and disabled with the last associated device disable.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  drivers/hwtracing/coresight/coresight-cti.c   | 87 +++++++++++++++++++
>  .../hwtracing/coresight/coresight-platform.c  | 23 +++++
>  drivers/hwtracing/coresight/coresight-priv.h  |  6 ++
>  drivers/hwtracing/coresight/coresight.c       | 58 +++++++++++--
>  include/linux/coresight.h                     |  5 ++
>  5 files changed, 173 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> index 369488dd7b8e..cf116463149a 100644
> --- a/drivers/hwtracing/coresight/coresight-cti.c
> +++ b/drivers/hwtracing/coresight/coresight-cti.c
> @@ -440,6 +440,90 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
>  	return err;
>  }
>  
> +/*
> + * Look for a matching connection device name in the list of
> + * connections. If found then swap in the csdev name and return
> + * found.
> + */
> +static bool
> +cti_match_con_name(struct cti_device *ctidev, const char *node_name,
> +		   const char *csdev_name)
> +{
> +	struct cti_trig_con *trig_con;
> +
> +	list_for_each_entry(trig_con, &ctidev->trig_cons, node) {
> +		if (trig_con->con_dev_name) {
> +			if (!strcmp(node_name, trig_con->con_dev_name)) {
> +				/* match: so swap in csdev name */
> +				kfree(trig_con->con_dev_name);
> +				trig_con->con_dev_name =
> +					kstrdup(csdev_name, GFP_KERNEL);
> +				return true;
> +			}
> +		}
> +	}
> +	return false;
> +}
> +
> +/*
> + * Search the cti list to add an associated CTI into the supplied CS device
> + * This will set the association if CTI declared before the CS device
> + */
> +void cti_add_assoc_to_csdev(struct coresight_device *csdev)
> +{
> +	struct cti_drvdata *ect_item;
> +	struct cti_device *ctidev;
> +	const char *node_name = NULL, *csdev_name;
> +
> +	/* protect the list */
> +	mutex_lock(&ect_mutex);
> +
> +	/* exit if current is an ECT device.*/
> +	if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net))
> +		goto cti_add_done;
> +
> +	/* if we didn't find the csdev previously we used the fwnode name */
> +	node_name = coresight_get_fwnode_name(csdev->dev.parent);
> +
> +	if (!node_name)
> +		goto cti_add_done;
> +
> +	/* this is the name we want to use for the association */
> +	csdev_name = dev_name(&csdev->dev);
> +
> +	/* for each CTI in list... */
> +	list_for_each_entry(ect_item, &ect_net, node) {
> +		ctidev = &ect_item->ctidev;
> +		if (cti_match_con_name(ctidev, node_name, csdev_name)) {
> +			/*
> +			 * if we found a matching name then update the
> +			 * association pointers.
> +			 */
> +			csdev->ect_dev = ect_item->csdev;
> +			goto cti_add_done;
> +		}
> +	}
> +cti_add_done:
> +	mutex_unlock(&ect_mutex);
> +}
> +EXPORT_SYMBOL_GPL(cti_add_assoc_to_csdev);
> +
> +/*
> + * Update the cross references where the associated device was found
> + * while we were building the connection info. This will occur if the
> + * assoc device was registered before the CTI.
> + */
> +static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)
> +{
> +	struct cti_trig_con *tc;
> +	struct cti_device *ctidev = &drvdata->ctidev;
> +
> +	list_for_each_entry(tc, &ctidev->trig_cons, node) {
> +		if (tc->con_dev)
> +			tc->con_dev->ect_dev = drvdata->csdev;
> +	}
> +}
> +
>  /** cti ect operations **/
>  int cti_enable(struct coresight_device *csdev)
>  {
> @@ -574,6 +658,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
>  	drvdata->csdev_release = drvdata->csdev->dev.release;
>  	drvdata->csdev->dev.release = cti_device_release;
>  
> +	/* set any cross references */
> +	cti_update_conn_xrefs(drvdata);
> +
>  	/* all done - dec pm refcount */
>  	pm_runtime_put(&adev->dev);
>  	dev_info(&drvdata->csdev->dev, "CTI initialized\n");
> diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
> index 3c5bee429105..6721cb1af5fe 100644
> --- a/drivers/hwtracing/coresight/coresight-platform.c
> +++ b/drivers/hwtracing/coresight/coresight-platform.c
> @@ -293,6 +293,12 @@ static int of_get_coresight_platform_data(struct device *dev,
>  
>  	return 0;
>  }
> +
> +static inline const char *of_coresight_get_node_name(struct device *dev)
> +{
> +	return dev->of_node->full_name;
> +}
> +
>  #else
>  static inline int
>  of_get_coresight_platform_data(struct device *dev,
> @@ -305,6 +311,11 @@ static inline int of_coresight_get_cpu(struct device *dev)
>  {
>  	return -ENODEV;
>  }
> +
> +static inline const char *of_coresight_get_node_name(struct device *dev)
> +{
> +	return NULL;
> +}
>  #endif
>  
>  #ifdef CONFIG_ACPI
> @@ -766,6 +777,18 @@ static inline int acpi_coresight_get_cpu(struct device *dev)
>  }
>  #endif
>  
> +const char *coresight_get_fwnode_name(struct device *dev)
> +{
> +	const char *node_name = NULL;
> +	struct fwnode_handle *fwnode = dev_fwnode(dev);
> +
> +	if (is_of_node(fwnode))
> +		node_name = of_coresight_get_node_name(dev);
> +
> +	return node_name;
> +}
> +EXPORT_SYMBOL_GPL(coresight_get_fwnode_name);
> +
>  int coresight_get_cpu(struct device *dev)
>  {
>  	if (is_of_node(dev->fwnode))
> diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> index aba6b789c969..484e5ec593bb 100644
> --- a/drivers/hwtracing/coresight/coresight-priv.h
> +++ b/drivers/hwtracing/coresight/coresight-priv.h
> @@ -162,6 +162,12 @@ static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
>  static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
>  #endif
>  
> +#ifdef CONFIG_CORESIGHT_CTI
> +extern void cti_add_assoc_to_csdev(struct coresight_device *csdev);
> +#else
> +static inline void cti_add_assoc_to_csdev(struct coresight_device *csdev) {}
> +#endif
> +
>  /*
>   * Macros and inline functions to handle CoreSight UCI data and driver
>   * private data in AMBA ID table entries, and extract data values.
> diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
> index 1a5fdf2710ff..7657be009246 100644
> --- a/drivers/hwtracing/coresight/coresight.c
> +++ b/drivers/hwtracing/coresight/coresight.c
> @@ -216,6 +216,31 @@ void coresight_disclaim_device(void __iomem *base)
>  	CS_LOCK(base);
>  }
>  
> +/* enable or disable an associated CTI device of the supplied CS device */
> +static int
> +coresight_control_assoc_ectdev(struct coresight_device *csdev, bool enable)
> +{
> +	int ect_ret = 0;
> +	struct coresight_device *ect_csdev = csdev->ect_dev;
> +
> +	if (!ect_csdev)
> +		return 0;
> +
> +	if (enable) {
> +		if (ect_ops(ect_csdev)->enable)
> +			ect_ret = ect_ops(ect_csdev)->enable(ect_csdev);
> +	} else {
> +		if (ect_ops(ect_csdev)->disable)
> +			ect_ret = ect_ops(ect_csdev)->disable(ect_csdev);
> +	}
> +
> +	/* output warning if ECT enable is preventing trace operation */
> +	if (ect_ret)
> +		dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n",
> +		 dev_name(&ect_csdev->dev), enable ? "enable" : "disable");

Indentation problem - please replace with:

                dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n",
                         dev_name(&ect_csdev->dev),
                         enable ? "enable" : "disable");

> +	return ect_ret;
> +}
> +
>  static int coresight_enable_sink(struct coresight_device *csdev,
>  				 u32 mode, void *data)
>  {
> @@ -228,11 +253,15 @@ static int coresight_enable_sink(struct coresight_device *csdev,
>  	if (!sink_ops(csdev)->enable)
>  		return -EINVAL;
>  
> -	ret = sink_ops(csdev)->enable(csdev, mode, data);
> +	ret = coresight_control_assoc_ectdev(csdev, true);
>  	if (ret)
>  		return ret;
> +	ret = sink_ops(csdev)->enable(csdev, mode, data);
> +	if (ret) {
> +		coresight_control_assoc_ectdev(csdev, false);
> +		return ret;
> +	}
>  	csdev->enable = true;
> -

Unneeded modification.

With the above changes:
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

>  	return 0;
>  }
>  
> @@ -246,6 +275,7 @@ static void coresight_disable_sink(struct coresight_device *csdev)
>  	ret = sink_ops(csdev)->disable(csdev);
>  	if (ret)
>  		return;
> +	coresight_control_assoc_ectdev(csdev, false);
>  	csdev->enable = false;
>  }
>  
> @@ -269,8 +299,15 @@ static int coresight_enable_link(struct coresight_device *csdev,
>  	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0)
>  		return outport;
>  
> -	if (link_ops(csdev)->enable)
> -		ret = link_ops(csdev)->enable(csdev, inport, outport);
> +	if (link_ops(csdev)->enable) {
> +		ret = coresight_control_assoc_ectdev(csdev, true);
> +		if (!ret) {
> +			ret = link_ops(csdev)->enable(csdev, inport, outport);
> +			if (ret)
> +				coresight_control_assoc_ectdev(csdev, false);
> +		}
> +	}
> +
>  	if (!ret)
>  		csdev->enable = true;
>  
> @@ -300,8 +337,10 @@ static void coresight_disable_link(struct coresight_device *csdev,
>  		nr_conns = 1;
>  	}
>  
> -	if (link_ops(csdev)->disable)
> +	if (link_ops(csdev)->disable) {
>  		link_ops(csdev)->disable(csdev, inport, outport);
> +		coresight_control_assoc_ectdev(csdev, false);
> +	}
>  
>  	for (i = 0; i < nr_conns; i++)
>  		if (atomic_read(&csdev->refcnt[i]) != 0)
> @@ -322,9 +361,14 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
>  
>  	if (!csdev->enable) {
>  		if (source_ops(csdev)->enable) {
> -			ret = source_ops(csdev)->enable(csdev, NULL, mode);
> +			ret = coresight_control_assoc_ectdev(csdev, true);
>  			if (ret)
>  				return ret;
> +			ret = source_ops(csdev)->enable(csdev, NULL, mode);
> +			if (ret) {
> +				coresight_control_assoc_ectdev(csdev, false);
> +				return ret;
> +			};
>  		}
>  		csdev->enable = true;
>  	}
> @@ -347,6 +391,7 @@ static bool coresight_disable_source(struct coresight_device *csdev)
>  	if (atomic_dec_return(csdev->refcnt) == 0) {
>  		if (source_ops(csdev)->disable)
>  			source_ops(csdev)->disable(csdev, NULL);
> +		coresight_control_assoc_ectdev(csdev, false);
>  		csdev->enable = false;
>  	}
>  	return !csdev->enable;
> @@ -1252,6 +1297,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
>  
>  	coresight_fixup_device_conns(csdev);
>  	coresight_fixup_orphan_conns(csdev);
> +	cti_add_assoc_to_csdev(csdev);
>  
>  	mutex_unlock(&coresight_mutex);
>  
> diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> index b3e582d96a34..b5dc9baf0c58 100644
> --- a/include/linux/coresight.h
> +++ b/include/linux/coresight.h
> @@ -163,6 +163,8 @@ struct coresight_connection {
>   *		activated but not yet enabled.  Enabling for a _sink_
>   *		appens when a source has been selected for that it.
>   * @ea:		Device attribute for sink representation under PMU directory.
> + * @ect_dev:	Associated cross trigger device. Not part of the trace data
> + *		path or connections.
>   */
>  struct coresight_device {
>  	struct coresight_platform_data *pdata;
> @@ -176,6 +178,8 @@ struct coresight_device {
>  	/* sink specific fields */
>  	bool activated;	/* true only if a sink is part of a path */
>  	struct dev_ext_attribute *ea;
> +	/* cross trigger handling */
> +	struct coresight_device *ect_dev;
>  };
>  
>  /*
> @@ -341,5 +345,6 @@ static inline bool coresight_loses_context_with_cpu(struct device *dev)
>  extern int coresight_get_cpu(struct device *dev);
>  
>  struct coresight_platform_data *coresight_get_platform_data(struct device *dev);
> +extern const char *coresight_get_fwnode_name(struct device *dev);
>  
>  #endif
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 09/14] coresight: cti: Add connection information to sysfs
  2019-11-19 23:19 ` [PATCH v5 09/14] coresight: cti: Add connection information to sysfs Mike Leach
@ 2019-11-27 18:09   ` Mathieu Poirier
  2019-12-06 16:24     ` Mike Leach
  2019-12-02  9:47   ` Suzuki Kuruppassery Poulose
  1 sibling, 1 reply; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-27 18:09 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:07PM +0000, Mike Leach wrote:
> Dynamically adds sysfs attributes for all connections defined in the CTI.
> 
> Each connection has a triggers<N> sub-directory with name, in_signals,
> in_types, out_signals and out_types as read-only parameters in the
> directory. in_ or out_ parameters may be omitted if there are no in or
> out signals for the connection.
> 
> Additionally each device has a nr_cons in the connections sub-directory.
> 
> This allows clients to explore the connection and trigger signal details
> without needing to refer to device tree or specification of the device.
> 
> Standardised type information is provided for certain common functions -
> e.g. snk_full for a trigger from a sink indicating full. Otherwise type
> defaults to genio.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  .../hwtracing/coresight/coresight-cti-sysfs.c | 376 +++++++++++++++++-
>  drivers/hwtracing/coresight/coresight-cti.c   |  13 +-
>  drivers/hwtracing/coresight/coresight-cti.h   |  11 +-
>  3 files changed, 396 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> index f800402f73da..91986732506f 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> @@ -8,6 +8,67 @@
>  
>  #include "coresight-cti.h"
>  
> +/*
> + * Declare the number of static declared attribute groups
> + * Value includes groups + NULL value at end of table.
> + */
> +#define CORESIGHT_CTI_STATIC_GROUPS_MAX 5
> +
> +/*
> + * List of trigger signal type names. Match the constants declared in
> + * include\dt-bindings\arm\coresight-cti-dt.h
> + */
> +static const char * const sig_type_names[] = {
> +	"genio",	/* GEN_IO */
> +	"intreq",	/* GEN_INTREQ */
> +	"intack",	/* GEN_INTACK */
> +	"haltreq",	/* GEN_HALTREQ */
> +	"restartreq",	/* GEN_RESTARTREQ */
> +	"pe_edbgreq",	/* PE_EDBGREQ */
> +	"pe_dbgrestart",/* PE_DBGRESTART */
> +	"pe_ctiirq",	/* PE_CTIIRQ */
> +	"pe_pmuirq",	/* PE_PMUIRQ */
> +	"pe_dbgtrigger",/* PE_DBGTRIGGER */
> +	"etm_extout",	/* ETM_EXTOUT */
> +	"etm_extin",	/* ETM_EXTIN */
> +	"snk_full",	/* SNK_FULL */
> +	"snk_acqcomp",	/* SNK_ACQCOMP */
> +	"snk_flushcomp",/* SNK_FLUSHCOMP */
> +	"snk_flushin",	/* SNK_FLUSHIN */
> +	"snk_trigin",	/* SNK_TRIGIN */
> +	"stm_asyncout",	/* STM_ASYNCOUT */
> +	"stm_tout_spte",/* STM_TOUT_SPTE */
> +	"stm_tout_sw",	/* STM_TOUT_SW */
> +	"stm_tout_hete",/* STM_TOUT_HETE */
> +	"stm_hwevent",	/* STM_HWEVENT */
> +	"ela_tstart",	/* ELA_TSTART */
> +	"ela_tstop",	/* ELA_TSTOP */
> +	"ela_dbgreq",	/* ELA_DBGREQ */
> +};
> +
> +/* Show function pointer used in the connections dynamic declared attributes*/
> +typedef ssize_t (*p_show_fn)(struct device *dev, struct device_attribute *attr,
> +			     char *buf);
> +
> +/* Connection attribute types */
> +enum cti_conn_attr_type {
> +	CTI_CON_ATTR_NAME,
> +	CTI_CON_ATTR_TRIGIN_SIG,
> +	CTI_CON_ATTR_TRIGOUT_SIG,
> +	CTI_CON_ATTR_TRIGIN_TYPES,
> +	CTI_CON_ATTR_TRIGOUT_TYPES,
> +	CTI_CON_ATTR_MAX,
> +};
> +
> +/* Names for the connection attributes */
> +static const char * const con_attr_names[CTI_CON_ATTR_MAX] = {
> +	"name",
> +	"in_signals",
> +	"out_signals",
> +	"in_types",
> +	"out_types",
> +};
> +
>  /* basic attributes */
>  static ssize_t enable_show(struct device *dev,
>  			   struct device_attribute *attr,
> @@ -66,10 +127,21 @@ static ssize_t ctmid_show(struct device *dev,
>  }
>  static DEVICE_ATTR_RO(ctmid);
>  
> +static ssize_t nr_trigger_cons_show(struct device *dev,
> +				    struct device_attribute *attr,
> +				    char *buf)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +
> +	return scnprintf(buf, PAGE_SIZE, "%d\n", drvdata->ctidev.nr_trig_con);
> +}
> +static DEVICE_ATTR_RO(nr_trigger_cons);
> +
>  /* attribute and group sysfs tables. */
>  static struct attribute *coresight_cti_attrs[] = {
>  	&dev_attr_enable.attr,
>  	&dev_attr_ctmid.attr,
> +	&dev_attr_nr_trigger_cons.attr,

I think it looks much getter that way - thanks for moving that.

>  	NULL,
>  };
>  
> @@ -818,7 +890,306 @@ static struct attribute *coresight_cti_channel_attrs[] = {
>  	NULL,
>  };
>  
> -/* sysfs groups */
> +/* Create the connections trigger groups and attrs dynamically */
> +/*
> + * Each connection has dynamic group triggers<N> + name, trigin/out sigs/types
> + * attributes, + each device has static nr_trigger_cons giving the number
> + * of groups. e.g. in sysfs:-
> + * /cti_<name>/triggers0
> + * /cti_<name>/triggers1
> + * /cti_<name>/nr_trigger_cons
> + * where nr_trigger_cons = 2
> + */
> +static ssize_t con_name_show(struct device *dev,
> +			     struct device_attribute *attr,
> +			     char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +
> +	return scnprintf(buf, PAGE_SIZE, "%s\n", con->con_dev_name);
> +}
> +
> +static ssize_t trigin_sig_show(struct device *dev,
> +			       struct device_attribute *attr,
> +			       char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *cfg = &drvdata->config;
> +	unsigned long mask = con->con_in->used_mask;
> +
> +	return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
> +}
> +
> +static ssize_t trigout_sig_show(struct device *dev,
> +				struct device_attribute *attr,
> +				char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *cfg = &drvdata->config;
> +	unsigned long mask = con->con_out->used_mask;
> +
> +	return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
> +}
> +
> +/* convert a sig type id to a name */
> +static const char *
> +cti_sig_type_name(struct cti_trig_con *con, int used_count, bool in)
> +{
> +	int idx = 0;
> +	struct cti_trig_grp *grp = in ? con->con_in : con->con_out;
> +
> +	if (grp->sig_types) {
> +		if (used_count < grp->nr_sigs)
> +			idx = grp->sig_types[used_count];
> +	}
> +	return sig_type_names[idx];
> +}
> +
> +static ssize_t trigin_type_show(struct device *dev,
> +				struct device_attribute *attr,
> +				char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +	int sig_idx, used = 0, b_sz = PAGE_SIZE;
> +	const char *name;
> +
> +	for (sig_idx = 0; sig_idx < con->con_in->nr_sigs; sig_idx++) {
> +		name = cti_sig_type_name(con, sig_idx, true);
> +		used += scnprintf(buf + used, b_sz - used, "%s ", name);
> +	}
> +	used += scnprintf(buf + used, b_sz - used, "\n");
> +	return used;
> +}
> +
> +static ssize_t trigout_type_show(struct device *dev,
> +				 struct device_attribute *attr,
> +				 char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +	int sig_idx, used = 0, b_sz = PAGE_SIZE;
> +	const char *name;
> +
> +	for (sig_idx = 0; sig_idx < con->con_out->nr_sigs; sig_idx++) {
> +		name = cti_sig_type_name(con, sig_idx, false);
> +		used += scnprintf(buf + used, b_sz - used, "%s ", name);
> +	}
> +	used += scnprintf(buf + used, b_sz - used, "\n");
> +	return used;
> +}
> +
> +/*
> + * Array of show function names declared above to allow selection
> + * for the connection attributes
> + */
> +static p_show_fn show_fns[CTI_CON_ATTR_MAX] = {
> +	con_name_show,
> +	trigin_sig_show,
> +	trigout_sig_show,
> +	trigin_type_show,
> +	trigout_type_show,
> +};
> +
> +static int cti_create_con_sysfs_attr(struct cti_trig_con *con,
> +				     enum cti_conn_attr_type attr_type,
> +				     int attr_idx)
> +{
> +	struct dev_ext_attribute *dev_ext_attr = 0;
> +	char *name = 0;
> +
> +	dev_ext_attr = kzalloc(sizeof(struct dev_ext_attribute), GFP_KERNEL);
> +	if (dev_ext_attr) {
> +		name = kstrdup(con_attr_names[attr_type], GFP_KERNEL);
> +		if (name) {
> +			/* fill out the underlying attribute struct */
> +			dev_ext_attr->attr.attr.name = name;
> +			dev_ext_attr->attr.attr.mode = 0444;
> +
> +			/* now the device_attribute struct */
> +			dev_ext_attr->attr.show = show_fns[attr_type];
> +		} else {
> +			kfree(dev_ext_attr);
> +			return -ENOMEM;
> +		}
> +	} else {
> +		return -ENOMEM;
> +	}
> +	dev_ext_attr->var = con;
> +	con->con_attrs[attr_idx] = &dev_ext_attr->attr.attr;
> +	return 0;
> +}
> +
> +static struct attribute_group *
> +cti_create_con_sysfs_group(struct cti_device *ctidev, int con_idx,
> +			   struct cti_trig_con *con)
> +{
> +	struct attribute_group *group = NULL;
> +
> +	group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
> +	if (!group)
> +		return NULL;
> +
> +	group->name = kasprintf(GFP_KERNEL, "triggers%d", con_idx);
> +	if (!group->name) {
> +		kfree(group);
> +		return NULL;
> +	}
> +
> +	ctidev->con_groups[con_idx + CORESIGHT_CTI_STATIC_GROUPS_MAX - 1]
> +		= group;

        idx = con_idx + CORESIGHT_CTI_STATIC_GROUPS_MAX - 1;
        ctidev->con_groups[idx] = group;

> +	con->attr_group = group;
> +	return group;
> +}
> +
> +/* create a triggers connection group and the attributes for that group */
> +static int cti_create_con_attr_set(int con_idx, struct cti_device *ctidev,
> +				   struct cti_trig_con *con)
> +{
> +	struct attribute_group *attr_group = NULL;
> +	int attr_idx = 0;
> +	int err = -ENOMEM;
> +
> +	attr_group = cti_create_con_sysfs_group(ctidev, con_idx, con);
> +	if (!attr_group)
> +		return -ENOMEM;
> +
> +	/* allocate NULL terminated array of attributes */
> +	con->con_attrs = kcalloc(CTI_CON_ATTR_MAX + 1,
> +				 sizeof(struct attribute *),
> +				 GFP_KERNEL);
> +	if (!con->con_attrs)
> +		return -ENOMEM;
> +
> +	err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_NAME, attr_idx++);
> +	if (err)
> +		return err;
> +
> +	if (con->con_in->nr_sigs > 0) {

I think we should check the validity of con->con_in before proceeding,
especially if people can do their HW however they want.  Same for con->con_out
below.

> +		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_SIG,
> +						attr_idx++);
> +		if (err)
> +			return err;
> +
> +		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_TYPES,
> +						attr_idx++);
> +		if (err)
> +			return err;
> +	}
> +
> +	if (con->con_in->nr_sigs > 0) {

        if (con->con_out->nr_sigs > 0)

> +		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_SIG,
> +						attr_idx++);
> +		if (err)
> +			return err;
> +
> +		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_TYPES,
> +						attr_idx++);
> +		if (err)
> +			return err;
> +	}
> +	attr_group->attrs = con->con_attrs;
> +	return 0;
> +}
> +
> +/* create the array of group pointers for the CTI sysfs groups */
> +int cti_create_cons_groups(struct cti_device *ctidev)
> +{
> +	int i, nr_groups;
> +
> +	/* nr groups - dynamic + static + NULL terminator */
> +	nr_groups = ctidev->nr_trig_con + CORESIGHT_CTI_STATIC_GROUPS_MAX;
> +	ctidev->con_groups = kcalloc(nr_groups,
> +				     sizeof(struct attribute_group *),
> +				     GFP_KERNEL);
> +	if (!ctidev->con_groups)
> +		return -ENOMEM;
> +
> +	/* populate first locations with the static set of groups */
> +	for (i = 0; i < (CORESIGHT_CTI_STATIC_GROUPS_MAX - 1); i++)
> +		ctidev->con_groups[i] = coresight_cti_groups[i];
> +
> +	return 0;
> +}
> +
> +int cti_create_cons_sysfs(struct cti_drvdata *drvdata)
> +{
> +	struct cti_device *ctidev = &drvdata->ctidev;
> +	int err, con_idx = 0;
> +	struct cti_trig_con *tc = NULL;
> +
> +	err = cti_create_cons_groups(ctidev);
> +	if (err)
> +		return err;
> +
> +	/* add dynamic set for each connection */
> +	list_for_each_entry(tc, &ctidev->trig_cons, node) {
> +		err = cti_create_con_attr_set(con_idx++, ctidev, tc);
> +		if (err)
> +			goto cons_sysfs_err;
> +	}
> +	return 0;
> +
> +cons_sysfs_err:
> +	cti_destroy_cons_sysfs(ctidev);
> +	return err;
> +}
> +
> +void cti_free_con_attr(struct attribute *con_attr)
> +{
> +	struct device_attribute *dattr =
> +		container_of(con_attr, struct device_attribute, attr);
> +	struct dev_ext_attribute *dev_ext_attr =
> +		container_of(dattr, struct dev_ext_attribute, attr);
> +	kfree(con_attr->name);
> +	kfree(dev_ext_attr);
> +}
> +
> +void cti_free_con_group(struct attribute_group *attr_group)
> +{
> +	if (attr_group) {
> +		kfree(attr_group->name);
> +		kfree(attr_group);
> +	}
> +}
> +
> +void cti_destroy_cons_attr_set(int con_idx, struct cti_device *ctidev,
> +			       struct cti_trig_con *con)
> +{
> +	int i;
> +
> +	if (con->con_attrs) {
> +		for (i = 0; i < CTI_CON_ATTR_MAX; i++) {
> +			if (con->con_attrs[i])
> +				cti_free_con_attr(con->con_attrs[i]);
> +		}
> +		kfree(con->con_attrs);
> +	}
> +	cti_free_con_group(con->attr_group);
> +}
> +
> +void cti_destroy_cons_sysfs(struct cti_device *ctidev)
> +{
> +	struct cti_trig_con *tc;
> +	int con_idx = 0;
> +
> +	list_for_each_entry(tc, &ctidev->trig_cons, node) {
> +		cti_destroy_cons_attr_set(con_idx++, ctidev, tc);
> +	}
> +	kfree(ctidev->con_groups);
> +}
> +
> +/* attribute and group sysfs tables. */
>  static const struct attribute_group coresight_cti_group = {
>  	.attrs = coresight_cti_attrs,
>  };
> @@ -838,7 +1209,8 @@ static const struct attribute_group coresight_cti_channels_group = {
>  	.name = "channels",
>  };
>  
> -const struct attribute_group *coresight_cti_groups[] = {
> +const struct attribute_group *
> +coresight_cti_groups[CORESIGHT_CTI_STATIC_GROUPS_MAX] = {
>  	&coresight_cti_group,
>  	&coresight_cti_mgmt_group,
>  	&coresight_cti_regs_group,
> diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> index cf116463149a..c3d63cc53bdd 100644
> --- a/drivers/hwtracing/coresight/coresight-cti.c
> +++ b/drivers/hwtracing/coresight/coresight-cti.c
> @@ -561,6 +561,9 @@ static void cti_device_release(struct device *dev)
>  
>  	mutex_lock(&ect_mutex);
>  
> +	/* clear the dynamic sysfs associate with connections */
> +	cti_destroy_cons_sysfs(&drvdata->ctidev);
> +
>  	/* remove from the list */
>  	list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
>  		if (ect_item == drvdata) {
> @@ -636,12 +639,20 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
>  		goto err_out;
>  	}
>  
> +	/* create dynamic attributes for connections */
> +	ret = cti_create_cons_sysfs(drvdata);
> +	if (ret) {
> +		pr_err("%s: create dynamic sysfs entries failed\n",
> +		       cti_desc.name);
> +		goto err_out;
> +	}
> +
>  	/* set up coresight component description */
>  	cti_desc.pdata = pdata;
>  	cti_desc.type = CORESIGHT_DEV_TYPE_ECT;
>  	cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI;
>  	cti_desc.ops = &cti_ops;
> -	cti_desc.groups = coresight_cti_groups;
> +	cti_desc.groups = drvdata->ctidev.con_groups;
>  	cti_desc.dev = dev;
>  	drvdata->csdev = coresight_register(&cti_desc);
>  	if (IS_ERR(drvdata->csdev)) {
> diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
> index 9a22f6fcad65..dc5b265acf5e 100644
> --- a/drivers/hwtracing/coresight/coresight-cti.h
> +++ b/drivers/hwtracing/coresight/coresight-cti.h
> @@ -74,6 +74,8 @@ struct cti_trig_grp {
>   * @con_dev: coresight device connected to the CTI, NULL if not CS device
>   * @con_dev_name: name of connected device (CS or CPU)
>   * @node: entry node in list of connections.
> + * @con_attrs: Dynamic sysfs attributes specific to this connection.
> + * @attr_group: Dynamic attribute group created for this connection.
>   */
>  struct cti_trig_con {
>  	struct cti_trig_grp *con_in;
> @@ -81,6 +83,8 @@ struct cti_trig_con {
>  	struct coresight_device *con_dev;
>  	char *con_dev_name;
>  	struct list_head node;
> +	struct attribute **con_attrs;
> +	struct attribute_group *attr_group;
>  };
>  
>  /**
> @@ -91,12 +95,15 @@ struct cti_trig_con {
>   *          assumed there is a single CTM per SoC, ID 0).
>   * @trig_cons: list of connections to this device.
>   * @cpu: CPU ID if associated with CPU, -1 otherwise.
> + * @con_groups: combined static and dynamic sysfs groups for trigger
> + *		connections.
>   */
>  struct cti_device {
>  	int nr_trig_con;
>  	u32 ctm_id;
>  	struct list_head trig_cons;
>  	int cpu;
> +	const struct attribute_group **con_groups;
>  };
>  
>  /**
> @@ -111,7 +118,7 @@ struct cti_device {
>   * @trig_in_use: bitfield of in triggers registered as in use.
>   * @trig_out_use: bitfield of out triggers registered as in use.
>   * @trig_out_filter: bitfield of out triggers that are blocked if filter
> - *	             enabled. Typically this would be dbgreq / restart on
> + *		     enabled. Typically this would be dbgreq / restart on

Spurious change.

With the above:
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

>   *		     a core CTI.
>   * @trig_filter_enable: 1 if filtering enabled.
>   * @xtrig_rchan_sel: channel selection for xtrigger connection show.
> @@ -214,6 +221,8 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
>  			u32 channel_idx);
>  int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
>  		      u32 channel_idx);
> +int cti_create_cons_sysfs(struct cti_drvdata *drvdata);
> +void cti_destroy_cons_sysfs(struct cti_device *ctidev);
>  struct coresight_platform_data *
>  coresight_cti_get_platform_data(struct device *dev);
>  
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 10/14] dt-bindings: qcom: Add CTI options for qcom msm8916
  2019-11-19 23:19 ` [PATCH v5 10/14] dt-bindings: qcom: Add CTI options for qcom msm8916 Mike Leach
@ 2019-11-27 18:18   ` Mathieu Poirier
  0 siblings, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-27 18:18 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:08PM +0000, Mike Leach wrote:
> Adds system and CPU bound CTI definitions for Qualcom msm8916 platform
> (Dragonboard DB410C).
> System CTIs 2-11 are omitted as no information available at present.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  arch/arm64/boot/dts/qcom/msm8916.dtsi | 85 +++++++++++++++++++++++++--
>  1 file changed, 81 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> index 5ea9fb8f2f87..9589fc2cba22 100644
> --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
> +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
> @@ -8,6 +8,7 @@
>  #include <dt-bindings/reset/qcom,gcc-msm8916.h>
>  #include <dt-bindings/clock/qcom,rpmcc.h>
>  #include <dt-bindings/thermal/thermal.h>
> +#include <dt-bindings/arm/coresight-cti-dt.h>
>  
>  / {
>  	interrupt-parent = <&intc>;
> @@ -1357,7 +1358,7 @@
>  			cpu = <&CPU3>;
>  		};
>  
> -		etm@85c000 {
> +		etm0: etm@85c000 {
>  			compatible = "arm,coresight-etm4x", "arm,primecell";
>  			reg = <0x85c000 0x1000>;
>  
> @@ -1375,7 +1376,7 @@
>  			};
>  		};
>  
> -		etm@85d000 {
> +		etm1: etm@85d000 {
>  			compatible = "arm,coresight-etm4x", "arm,primecell";
>  			reg = <0x85d000 0x1000>;
>  
> @@ -1393,7 +1394,7 @@
>  			};
>  		};
>  
> -		etm@85e000 {
> +		etm2: etm@85e000 {
>  			compatible = "arm,coresight-etm4x", "arm,primecell";
>  			reg = <0x85e000 0x1000>;
>  
> @@ -1411,7 +1412,7 @@
>  			};
>  		};
>  
> -		etm@85f000 {
> +		etm3: etm@85f000 {
>  			compatible = "arm,coresight-etm4x", "arm,primecell";
>  			reg = <0x85f000 0x1000>;
>  
> @@ -1429,6 +1430,82 @@
>  			};
>  		};
>  
> +		/* System CTIs */
> +		/* CTI 0 - TMC connections */
> +		cti@810000 {
> +			compatible = "arm,coresight-cti", "arm,primecell";
> +			reg = <0x810000 0x1000>;
> +
> +			clocks = <&rpmcc RPM_QDSS_CLK>;
> +			clock-names = "apb_pclk";
> +		};
> +
> +		/* CTI 1 - TPIU connections */
> +		cti@811000 {
> +			compatible = "arm,coresight-cti", "arm,primecell";
> +			reg = <0x811000 0x1000>;
> +
> +			clocks = <&rpmcc RPM_QDSS_CLK>;
> +			clock-names = "apb_pclk";
> +		};
> +
> +		/* CTIs 2-11 - no information - not instantiated */
> +
> +		/* Core CTIs; CTIs 12-15 */
> +		/* CTI - CPU-0 */
> +		cti@858000 {
> +			compatible = "arm,coresight-cti", "arm,primecell";
> +			reg = <0x858000 0x1000>;
> +
> +			clocks = <&rpmcc RPM_QDSS_CLK>;
> +			clock-names = "apb_pclk";
> +
> +			arm,cti-v8-arch;
> +			cpu = <&CPU0>;
> +			arm,cs-dev-assoc = <&etm0>;
> +
> +		};
> +
> +		/* CTI - CPU-1 */
> +		cti@859000 {
> +			compatible = "arm,coresight-cti", "arm,primecell";
> +			reg = <0x859000 0x1000>;
> +
> +			clocks = <&rpmcc RPM_QDSS_CLK>;
> +			clock-names = "apb_pclk";
> +
> +			arm,cti-v8-arch;
> +			cpu = <&CPU1>;
> +			arm,cs-dev-assoc = <&etm1>;
> +		};
> +
> +		/* CTI - CPU-2 */
> +		cti@85a000 {
> +			compatible = "arm,coresight-cti", "arm,primecell";
> +			reg = <0x85a000 0x1000>;
> +
> +			clocks = <&rpmcc RPM_QDSS_CLK>;
> +			clock-names = "apb_pclk";
> +
> +			arm,cti-v8-arch;
> +			cpu = <&CPU2>;
> +			arm,cs-dev-assoc = <&etm2>;
> +		};
> +
> +		/* CTI - CPU-3 */
> +		cti@85b000 {
> +			compatible = "arm,coresight-cti", "arm,primecell";
> +			reg = <0x85b000 0x1000>;
> +
> +			clocks = <&rpmcc RPM_QDSS_CLK>;
> +			clock-names = "apb_pclk";
> +
> +			arm,cti-v8-arch;
> +			cpu = <&CPU3>;
> +			arm,cs-dev-assoc = <&etm3>;
> +		};
> +
> +

This looks good to me.  Since Andy Gross maintains this file you will have to CC
him on your next revision.  Right now chances are he hasn't see it. 

>  		venus: video-codec@1d00000 {
>  			compatible = "qcom,msm8916-venus";
>  			reg = <0x01d00000 0xff000>;
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 11/14] dt-bindings: arm: Juno platform - add CTI entries to device tree.
  2019-11-19 23:19 ` [PATCH v5 11/14] dt-bindings: arm: Juno platform - add CTI entries to device tree Mike Leach
@ 2019-11-27 18:25   ` Mathieu Poirier
  0 siblings, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-27 18:25 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:09PM +0000, Mike Leach wrote:
> Add in CTI entries for Juno r0, r1 and r2 to device tree entries.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  arch/arm64/boot/dts/arm/juno-base.dtsi    | 150 +++++++++++++++++++++-
>  arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi |  31 ++++-
>  arch/arm64/boot/dts/arm/juno-r1.dts       |  25 ++++
>  arch/arm64/boot/dts/arm/juno-r2.dts       |  25 ++++
>  arch/arm64/boot/dts/arm/juno.dts          |  25 ++++
>  5 files changed, 251 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi
> index 26a039a028b8..4db2eca87dbf 100644
> --- a/arch/arm64/boot/dts/arm/juno-base.dtsi
> +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
> @@ -108,7 +108,7 @@
>  	 * The actual size is just 4K though 64K is reserved. Access to the
>  	 * unmapped reserved region results in a DECERR response.
>  	 */
> -	etf@20010000 { /* etf0 */
> +	etf_sys0: etf@20010000 { /* etf0 */
>  		compatible = "arm,coresight-tmc", "arm,primecell";
>  		reg = <0 0x20010000 0 0x1000>;
>  
> @@ -132,7 +132,7 @@
>  		};
>  	};
>  
> -	tpiu@20030000 {
> +	tpiu_sys: tpiu@20030000 {
>  		compatible = "arm,coresight-tpiu", "arm,primecell";
>  		reg = <0 0x20030000 0 0x1000>;
>  
> @@ -185,7 +185,7 @@
>  		};
>  	};
>  
> -	etr@20070000 {
> +	etr_sys: etr@20070000 {
>  		compatible = "arm,coresight-tmc", "arm,primecell";
>  		reg = <0 0x20070000 0 0x1000>;
>  		iommus = <&smmu_etr 0>;
> @@ -203,7 +203,7 @@
>  		};
>  	};
>  
> -	stm@20100000 {
> +	stm_sys: stm@20100000 {
>  		compatible = "arm,coresight-stm", "arm,primecell";
>  		reg = <0 0x20100000 0 0x1000>,
>  		      <0 0x28000000 0 0x1000000>;
> @@ -280,6 +280,18 @@
>  		};
>  	};
>  
> +	cti0: cti@22020000 {
> +		compatible = "arm,coresight-cti", "arm,primecell";
> +		reg = <0 0x22020000 0 0x1000>;
> +
> +		clocks = <&soc_smc50mhz>;
> +		clock-names = "apb_pclk";
> +		power-domains = <&scpi_devpd 0>;
> +
> +		arm,cti-v8-arch;
> +		arm,cs-dev-assoc = <&etm0>;
> +	};
> +
>  	funnel@220c0000 { /* cluster0 funnel */
>  		compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
>  		reg = <0 0x220c0000 0 0x1000>;
> @@ -340,6 +352,18 @@
>  		};
>  	};
>  
> +	cti1: cti@22120000 {
> +		compatible = "arm,coresight-cti", "arm,primecell";
> +		reg = <0 0x22120000 0 0x1000>;
> +
> +		clocks = <&soc_smc50mhz>;
> +		clock-names = "apb_pclk";
> +		power-domains = <&scpi_devpd 0>;
> +
> +		arm,cti-v8-arch;
> +		arm,cs-dev-assoc = <&etm1>;
> +	};
> +
>  	cpu_debug2: cpu-debug@23010000 {
>  		compatible = "arm,coresight-cpu-debug", "arm,primecell";
>  		reg = <0x0 0x23010000 0x0 0x1000>;
> @@ -365,6 +389,18 @@
>  		};
>  	};
>  
> +	cti2: cti@23020000 {
> +		compatible = "arm,coresight-cti", "arm,primecell";
> +		reg = <0 0x23020000 0 0x1000>;
> +
> +		clocks = <&soc_smc50mhz>;
> +		clock-names = "apb_pclk";
> +		power-domains = <&scpi_devpd 0>;
> +
> +		arm,cti-v8-arch;
> +		arm,cs-dev-assoc = <&etm2>;
> +	};
> +
>  	funnel@230c0000 { /* cluster1 funnel */
>  		compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
>  		reg = <0 0x230c0000 0 0x1000>;
> @@ -437,6 +473,18 @@
>  		};
>  	};
>  
> +	cti3: cti@23120000 {
> +		compatible = "arm,coresight-cti", "arm,primecell";
> +		reg = <0 0x23120000 0 0x1000>;
> +
> +		clocks = <&soc_smc50mhz>;
> +		clock-names = "apb_pclk";
> +		power-domains = <&scpi_devpd 0>;
> +
> +		arm,cti-v8-arch;
> +		arm,cs-dev-assoc = <&etm3>;
> +	};
> +
>  	cpu_debug4: cpu-debug@23210000 {
>  		compatible = "arm,coresight-cpu-debug", "arm,primecell";
>  		reg = <0x0 0x23210000 0x0 0x1000>;
> @@ -462,6 +510,18 @@
>  		};
>  	};
>  
> +	cti4: cti@23220000 {
> +		compatible = "arm,coresight-cti", "arm,primecell";
> +		reg = <0 0x23220000 0 0x1000>;
> +
> +		clocks = <&soc_smc50mhz>;
> +		clock-names = "apb_pclk";
> +		power-domains = <&scpi_devpd 0>;
> +
> +		arm,cti-v8-arch;
> +		arm,cs-dev-assoc = <&etm4>;
> +	};
> +
>  	cpu_debug5: cpu-debug@23310000 {
>  		compatible = "arm,coresight-cpu-debug", "arm,primecell";
>  		reg = <0x0 0x23310000 0x0 0x1000>;
> @@ -487,6 +547,88 @@
>  		};
>  	};
>  
> +	cti5: cti@23320000 {
> +		compatible = "arm,coresight-cti", "arm,primecell";
> +		reg = <0 0x23320000 0 0x1000>;
> +
> +		clocks = <&soc_smc50mhz>;
> +		clock-names = "apb_pclk";
> +		power-domains = <&scpi_devpd 0>;
> +
> +		arm,cti-v8-arch;
> +		arm,cs-dev-assoc = <&etm5>;
> +	};
> +
> +
> +	cti@20020000 { /* sys_cti_0 */
> +		compatible = "arm,coresight-cti", "arm,primecell";
> +		reg = <0 0x20020000 0 0x1000>;
> +
> +		clocks = <&soc_smc50mhz>;
> +		clock-names = "apb_pclk";
> +		power-domains = <&scpi_devpd 0>;
> +
> +		trig-conns@0 {
> +			arm,trig-in-sigs=<2 3>;
> +			arm,trig-in-types=<SNK_FULL SNK_ACQCOMP>;
> +			arm,trig-out-sigs=<0 1>;
> +			arm,trig-out-types=<SNK_FLUSHIN SNK_TRIGIN>;
> +			arm,cs-dev-assoc = <&etr_sys>;
> +		};
> +
> +		trig-conns@1 {
> +			arm,trig-in-sigs=<0 1>;
> +			arm,trig-in-types=<SNK_FULL SNK_ACQCOMP>;
> +			arm,trig-out-sigs=<7 6>;
> +			arm,trig-out-types=<SNK_FLUSHIN SNK_TRIGIN>;
> +			arm,cs-dev-assoc = <&etf_sys0>;
> +		};
> +
> +		trig-conns@2 {
> +			arm,trig-in-sigs=<4 5 6 7>;
> +			arm,trig-in-types=<STM_TOUT_SPTE STM_TOUT_SW
> +					   STM_TOUT_HETE STM_ASYNCOUT>;
> +			arm,trig-out-sigs=<4 5>;
> +			arm,trig-out-types=<STM_HWEVENT STM_HWEVENT>;
> +			arm,cs-dev-assoc = <&stm_sys>;
> +		};
> +
> +		trig-conns@3 {
> +			arm,trig-out-sigs=<2 3>;
> +			arm,trig-out-types=<SNK_FLUSHIN SNK_TRIGIN>;
> +			arm,cs-dev-assoc = <&tpiu_sys>;
> +		};
> +	};
> +
> +	cti@20110000 { /* sys_cti_1 */
> +		compatible = "arm,coresight-cti", "arm,primecell";
> +		reg = <0 0x20110000 0 0x1000>;
> +
> +		clocks = <&soc_smc50mhz>;
> +		clock-names = "apb_pclk";
> +		power-domains = <&scpi_devpd 0>;
> +
> +		trig-conns@0 {
> +			arm,trig-in-sigs=<0>;
> +			arm,trig-in-types=<GEN_INTREQ>;
> +			arm,trig-out-sigs=<0>;
> +			arm,trig-out-types=<GEN_HALTREQ>;
> +			arm,trig-conn-name = "sys_profiler";
> +		};
> +
> +		trig-conns@1 {
> +			arm,trig-out-sigs=<2 3>;
> +			arm,trig-out-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> +			arm,trig-conn-name = "watchdog";
> +		};
> +
> +		trig-conns@2 {
> +			arm,trig-out-sigs=<1 6>;
> +			arm,trig-out-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> +			arm,trig-conn-name = "g_counter";
> +		};
> +	};
> +
>  	sram: sram@2e000000 {
>  		compatible = "arm,juno-sram-ns", "mmio-sram";
>  		reg = <0x0 0x2e000000 0x0 0x8000>;
> diff --git a/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi b/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi
> index eda3d9e18af6..308f4eee8b29 100644
> --- a/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi
> +++ b/arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi
> @@ -23,7 +23,7 @@
>  		};
>  	};
>  
> -	etf@20140000 { /* etf1 */
> +	etf_sys1: etf@20140000 { /* etf1 */
>  		compatible = "arm,coresight-tmc", "arm,primecell";
>  		reg = <0 0x20140000 0 0x1000>;
>  
> @@ -82,4 +82,33 @@
>  
>  		};
>  	};
> +
> +	cti@20160000 { /* sys_cti_2 */
> +		compatible = "arm,coresight-cti", "arm,primecell";
> +		reg = <0 0x20160000 0 0x1000>;
> +
> +		clocks = <&soc_smc50mhz>;
> +		clock-names = "apb_pclk";
> +		power-domains = <&scpi_devpd 0>;
> +
> +		trig-conns@0 {
> +			arm,trig-in-sigs=<0 1>;
> +			arm,trig-in-types=<SNK_FULL SNK_ACQCOMP>;
> +			arm,trig-out-sigs=<0 1>;
> +			arm,trig-out-types=<SNK_FLUSHIN SNK_TRIGIN>;
> +			arm,cs-dev-assoc = <&etf_sys1>;
> +		};
> +
> +		trig-conns@1 {
> +			arm,trig-in-sigs=<2 3 4>;
> +			arm,trig-in-types=<ELA_DBGREQ ELA_TSTART ELA_TSTOP>;
> +			arm,trig-conn-name = "ela_clus_0";
> +		};
> +
> +		trig-conns@2 {
> +			arm,trig-in-sigs=<5 6 7>;
> +			arm,trig-in-types=<ELA_DBGREQ ELA_TSTART ELA_TSTOP>;
> +			arm,trig-conn-name = "ela_clus_1";
> +		};
> +	};
>  };
> diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts
> index 5f290090b0cf..02aa51eb311d 100644
> --- a/arch/arm64/boot/dts/arm/juno-r1.dts
> +++ b/arch/arm64/boot/dts/arm/juno-r1.dts
> @@ -9,6 +9,7 @@
>  /dts-v1/;
>  
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/arm/coresight-cti-dt.h>
>  #include "juno-base.dtsi"
>  #include "juno-cs-r1r2.dtsi"
>  
> @@ -309,3 +310,27 @@
>  &cpu_debug5 {
>  	cpu = <&A53_3>;
>  };
> +
> +&cti0 {
> +	cpu = <&A57_0>;
> +};
> +
> +&cti1 {
> +	cpu = <&A57_1>;
> +};
> +
> +&cti2 {
> +	cpu = <&A53_0>;
> +};
> +
> +&cti3 {
> +	cpu = <&A53_1>;
> +};
> +
> +&cti4 {
> +	cpu = <&A53_2>;
> +};
> +
> +&cti5 {
> +	cpu = <&A53_3>;
> +};
> diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts b/arch/arm64/boot/dts/arm/juno-r2.dts
> index 305300dd521c..75bb27c2d4dc 100644
> --- a/arch/arm64/boot/dts/arm/juno-r2.dts
> +++ b/arch/arm64/boot/dts/arm/juno-r2.dts
> @@ -9,6 +9,7 @@
>  /dts-v1/;
>  
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/arm/coresight-cti-dt.h>
>  #include "juno-base.dtsi"
>  #include "juno-cs-r1r2.dtsi"
>  
> @@ -315,3 +316,27 @@
>  &cpu_debug5 {
>  	cpu = <&A53_3>;
>  };
> +
> +&cti0 {
> +	cpu = <&A72_0>;
> +};
> +
> +&cti1 {
> +	cpu = <&A72_1>;
> +};
> +
> +&cti2 {
> +	cpu = <&A53_0>;
> +};
> +
> +&cti3 {
> +	cpu = <&A53_1>;
> +};
> +
> +&cti4 {
> +	cpu = <&A53_2>;
> +};
> +
> +&cti5 {
> +	cpu = <&A53_3>;
> +};
> diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
> index f00cffbd032c..dbc22e70b62c 100644
> --- a/arch/arm64/boot/dts/arm/juno.dts
> +++ b/arch/arm64/boot/dts/arm/juno.dts
> @@ -9,6 +9,7 @@
>  /dts-v1/;
>  
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/arm/coresight-cti-dt.h>
>  #include "juno-base.dtsi"
>  
>  / {
> @@ -295,3 +296,27 @@
>  &cpu_debug5 {
>  	cpu = <&A53_3>;
>  };
> +
> +&cti0 {
> +	cpu = <&A57_0>;
> +};
> +
> +&cti1 {
> +	cpu = <&A57_1>;
> +};
> +
> +&cti2 {
> +	cpu = <&A53_0>;
> +};
> +
> +&cti3 {
> +	cpu = <&A53_1>;
> +};
> +
> +&cti4 {
> +	cpu = <&A53_2>;
> +};
> +
> +&cti5 {
> +	cpu = <&A53_3>;
> +};

Same comment for these files - Liviu, Sudeep and Lorenzo will need to be CC'ed. 

> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs
  2019-11-19 23:19 ` [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs Mike Leach
@ 2019-11-27 18:26   ` Suzuki Kuruppassery Poulose
  2019-11-29 12:47     ` Mike Leach
  2019-11-28 10:54   ` Suzuki Kuruppassery Poulose
  1 sibling, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-27 18:26 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

On 19/11/2019 23:19, Mike Leach wrote:
> Adds in sysfs programming support for the CTI function register sets.
> Allows direct manipulation of channel / trigger association registers.
> 
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>   .../hwtracing/coresight/coresight-cti-sysfs.c | 362 ++++++++++++++++++
>   drivers/hwtracing/coresight/coresight-cti.c   |  19 +
>   drivers/hwtracing/coresight/coresight-cti.h   |   5 +
>   3 files changed, 386 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> index 507f8eb487fe..02d3ee0c1278 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> @@ -109,6 +109,362 @@ static struct attribute *coresight_cti_mgmt_attrs[] = {
>   	NULL,
>   };
>   
> +/* CTI low level programming registers */
> +
> +/*
> + * Show a simple 32 bit value if enabled and powered.
> + * If inaccessible & pcached_val not NULL then show cached value.
> + */

Also I am not sure if it makes sense to mention that the value is cached.

> +static ssize_t cti_reg32_show(struct device *dev, char *buf,
> +			      u32 *pcached_val, int reg_offset)
> +{
> +	u32 val = 0;
   +	char *state = "";

> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *config = &drvdata->config;
> +
> +	spin_lock(&drvdata->spinlock);
> +	if ((reg_offset >= 0) && CTI_PWR_ENA(config)) {

minor nit: Personally I don't like the naming here. This could simply 
be: cti_accessible(config) , may be defined as a static inline function
instead of a macro:

static inline bool cti_accessible(struct cti_drvdata *drvdata)
{
	struct cti_config *cfg = &drvdata->config;

	return cfg->hw_powered && cfg->hw_enabled;
}


> +		CS_UNLOCK(drvdata->base);
> +		val = readl_relaxed(drvdata->base + reg_offset);
> +		if (pcached_val)
> +			*pcached_val = val;
> +		CS_LOCK(drvdata->base);
> +	} else if (pcached_val) {
> +		val = *pcached_val;

   +		state = " (cached)";
> +	}
> +	spin_unlock(&drvdata->spinlock);
> +	return scnprintf(buf, PAGE_SIZE, "%#x\n", val);
   +	return scnprintf(buf, PAGE_SIZE, "%#x%s\n", val, state);

> +}
> +
> +/*
> + * Store a simple 32 bit value.
> + * If pcached_val not NULL, then copy to here too,
> + * if reg_offset >= 0 then write through if enabled.
> + */
> +static ssize_t cti_reg32_store(struct device *dev, const char *buf,
> +			       size_t size, u32 *pcached_val, int reg_offset)


> +static ssize_t appclear_store(struct device *dev,
> +			      struct device_attribute *attr,
> +			      const char *buf, size_t size)
> +{
> +	unsigned long val;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *config = &drvdata->config;
> +
> +	if (kstrtoul(buf, 0, &val))
> +		return -EINVAL;
> +
> +	spin_lock(&drvdata->spinlock);
> +
> +	/* a 1'b1 in appclr clears down the same bit in appset*/

nit: a 0b1 ?

> +	config->ctiappset &= ~val;
> +
> +	/* write through if enabled */
> +	if (CTI_PWR_ENA(config))
> +		cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
> +	spin_unlock(&drvdata->spinlock);
> +	return size;
> +}
> +static DEVICE_ATTR_WO(appclear);
> +

Otherwise looks good to me.

Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 04/14] coresight: cti: Add sysfs trigger / channel programming API
  2019-11-19 23:19 ` [PATCH v5 04/14] coresight: cti: Add sysfs trigger / channel programming API Mike Leach
  2019-11-22 18:40   ` Mathieu Poirier
@ 2019-11-27 18:40   ` Suzuki Kuruppassery Poulose
  2019-11-29 13:01     ` Mike Leach
  1 sibling, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-27 18:40 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

On 19/11/2019 23:19, Mike Leach wrote:
> Adds a user API to allow programming of CTI by trigger ID and
> channel number. This will take the channel and trigger ID supplied
> by the user and program the appropriate register values.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---

> +
> +static ssize_t chan_xtrigs_view_show(struct device *dev,
> +				     struct device_attribute *attr,
> +				     char *buf)
> +{
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *cfg = &drvdata->config;
> +	int used = 0, reg_idx;
> +	int buf_sz = PAGE_SIZE;
> +	u32 chan_mask = BIT(cfg->xtrig_rchan_sel);
> +
> +	used += scnprintf(buf, buf_sz, "[%d] IN: ", cfg->xtrig_rchan_sel);
> +	for (reg_idx = 0;
> +	     reg_idx < drvdata->config.nr_trig_max;
> +	     reg_idx++) {
> +		if (chan_mask & cfg->ctiinen[reg_idx]) {
> +			used += scnprintf(buf + used, buf_sz - used, "%d ",
> +					  reg_idx);
> +		}
> +	}

As a security measure, we must make sure that we have space left in the
buffer. We could end up passing "negative" numbers for the size
argument, in the worst case.

> +
> +	used += scnprintf(buf + used, buf_sz - used, "OUT: ");
> +	for (reg_idx = 0;
> +	     reg_idx < drvdata->config.nr_trig_max;
> +	     reg_idx++) {
> +		if (chan_mask & cfg->ctiouten[reg_idx]) {
> +			used += scnprintf(buf + used, buf_sz - used, "%d ",
> +					  reg_idx);
> +		}
> +	}
> +	used += scnprintf(buf + used, buf_sz - used, "\n");
> +	return used;
> +}
> +static DEVICE_ATTR_RW(chan_xtrigs_view);


The rest looks fine to me.

Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 13/14] docs: coresight: Update documentation for CoreSight to cover CTI.
  2019-11-19 23:19 ` [PATCH v5 13/14] docs: coresight: Update documentation for CoreSight to cover CTI Mike Leach
@ 2019-11-27 19:00   ` Mathieu Poirier
  2019-12-02 10:43   ` Suzuki Kuruppassery Poulose
  1 sibling, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-27 19:00 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:11PM +0000, Mike Leach wrote:
> Add new document covering CTI / CTM usage in CoreSight.
> 
> Add section in coresight.rst introducing CTI and CTM modules with link
> to new document.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  .../trace/coresight/coresight-ect.rst         | 200 ++++++++++++++++++
>  Documentation/trace/coresight/coresight.rst   |  13 ++
>  2 files changed, 213 insertions(+)
>  create mode 100644 Documentation/trace/coresight/coresight-ect.rst
> 
> diff --git a/Documentation/trace/coresight/coresight-ect.rst b/Documentation/trace/coresight/coresight-ect.rst
> new file mode 100644
> index 000000000000..6448cf910f20
> --- /dev/null
> +++ b/Documentation/trace/coresight/coresight-ect.rst
> @@ -0,0 +1,200 @@
> +=============================================
> +CoreSight Embedded Cross Trigger (CTI & CTM).
> +=============================================
> +
> +    :Author:   Mike Leach <mike.leach@linaro.org>
> +    :Date:     November 2019
> +
> +Hardware Description
> +--------------------
> +
> +The CoreSight Cross Trigger Interface (CTI) is a hardware device that takes
> +individual input and output hardware signals known as triggers to and from
> +devices and interconnects them via the Cross Trigger Matrix (CTM) to other
> +devices via numbered channels, in order to propagate events between devices.
> +
> +e.g.::
> +
> + 0000000  in_trigs  :::::::
> + 0 C   0----------->:     :             +======>(other CTI channel IO)
> + 0  P  0<-----------:     :             v
> + 0   U 0  out_trigs :     : Channels  *****      :::::::
> + 0000000            : CTI :<=========>*CTM*<====>: CTI :---+
> + #######  in_trigs  :     : (id 0-3)  *****      :::::::   v
> + # ETM #----------->:     :                         ^   #######
> + #     #<-----------:     :                         +---# ETR #
> + ####### out_trigs  :::::::                             #######
> +
> +The CTI driver enables the programming of the CTI to attach triggers to
> +channels. When an input trigger becomes active, the attached channel will
> +become active. Any output trigger attached to that channel will also
> +become active. The active channel is propagated to other CTIs via the CTM,
> +activiating connected output triggers there, unless filtered by the CTI

s/activiating/activating

> +channel gate.
> +
> +It is also possible to activate a channel using system software directly
> +programming registers in the CTI.
> +
> +The CTIs are registered by the system to be associated with CPUs and/or other
> +CoreSight devices on the trace data path. When these devices are enabled the
> +attached CTIs will also be enabled. By default/on power up the CTIs have
> +no programmed trigger/channel attachments, so will not affect the system
> +until explicitly programmed.
> +
> +The hardware trigger connections between CTIs and devices is implementation
> +defined, unless the CPU/ETM combination is a v8 architecture, in which case
> +the connections have an architecturally defined standard layout.
> +
> +The hardware trigger signals can also be connected to non-CoreSight devices
> +(e.g. UART), or be propagated off chip as hardware IO lines.
> +
> +All the CTI devices are associated with a CTM. On many systems there will be a
> +single effective CTM (one CTM, or multiple CTMs all interconnected), but it is
> +possible that systems can have nets of CTIs+CTM that are not interconnected by
> +a CTM to each other. On these systems a CTM index is declared to associate
> +CTI devices that are interconnected via a given CTM.
> +
> +Sysfs files and directories
> +---------------------------
> +
> +The CTI devices appear on the existing CoreSight bus alongside the other
> +CoreSight devices::
> +
> +    >$ ls /sys/bus/coresight/devices
> +     cti_cpu0  cti_cpu2  cti_sys0  etm0  etm2  funnel0  replicator0  tmc_etr0
> +     cti_cpu1  cti_cpu3  cti_sys1  etm1  etm3  funnel1  tmc_etf0     tpiu0
> +
> +The ``cti_cpu<N>`` named CTIs are associated with a CPU, and any ETM used by
> +that core. the ``cti_sys<N>`` CTIs are general system infrastructure CTIs that
> +can be associated with other CoreSight devices, or other system hardware
> +capable of generating or using trigger signals.::
> +
> +  >$ ls /sys/bus/coresight/devices/etm0/cti_cpu0
> +  channels  ctmid  enable  nr_trigger_cons mgmt  power  regs  subsystem
> +  triggers0 triggers1  uevent
> +
> +*Key file items are:-*
> +   * ``enable``: enables/disables the CTI.
> +   * ``ctmid`` : associated CTM - only relevant if system has multiple CTI+CTM
> +     clusters that are not interconnected.
> +   * ``nr_trigger_cons`` : total connections - triggers<N> directories.
> +
> +*Sub-directories:-*
> +   * ``triggers<N>``: contains list of triggers for an individual connection.
> +   * ``channels``: Contains the channel API - CTI main programming interface.
> +   * ``regs``: Gives access to the raw programmable CTI regs.
> +   * ``mgmt``: the standard CoreSight management registers.
> +
> +
> +triggers<N> directories
> +~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Individual trigger connection information. This describes trigger signals for
> +CoreSight and non-CoreSight connections.
> +
> +Each triggers directory has a set of parameters describing the triggers for
> +the connection.
> +
> +   * ``name`` : name of connection
> +   * ``in_signals`` : input trigger signal indexes used in this connection.
> +   * ``in_types`` : functional types for in signals.
> +   * ``out_signals`` : output trigger signals for this connection.
> +   * ``out_types`` : functional types for out signals.
> +
> +e.g::
> +
> +    >$ ls ./cti_cpu0/triggers0/
> +    in_signals  in_types  name  out_signals  out_types
> +    >$ cat ./cti_cpu0/triggers0/name
> +    cpu0
> +    >$ cat ./cti_cpu0/triggers0/out_signals
> +    0-2
> +    >$ cat ./cti_cpu0/triggers0/out_types
> +    pe_edbgreq pe_dbgrestart pe_ctiirq
> +    >$ cat ./cti_cpu0/triggers0/in_signals
> +    0-1
> +    >$ cat ./cti_cpu0/triggers0/in_types
> +    pe_dbgtrigger pe_pmuirq
> +
> +If a connection has zero signals in either the 'in' or 'out' triggers then
> +those parameters will be omitted.
> +
> +Channels API Directory
> +~~~~~~~~~~~~~~~~~~~~~~
> +
> +This provides an easy way to attach triggers to channels, without needing
> +the multiple register operations that are required if manipluating the

s/manipluating/manipulating

> +'regs' sub-dir elements directly.
> +
> +A number of files provide this API::
> +
> +   >$ ls ./cti_sys0/channels/
> +   chan_clear         chan_inuse         chan_xtrigs_view      trigin_detach
> +   chan_free          chan_pulse         chan_xtrigs_view_sel  trigout_attach
> +   chan_gate_disable  chan_set           trig_filter_enable    trigout_detach
> +   chan_gate_enable   chan_xtrigs_reset  trigin_attach         trigout_filtered
> +
> +Most access to these elements take the form::
> +
> +  echo <chan> [<trigger>] > /<device_path>/<operation>
> +
> +where the optional <trigger> is only needed for trigXX_attach | detach
> +operations.
> +
> +e.g.::
> +
> +   >$ echo 0 1 > ./cti_sys0/channels/trigout_attach
> +   >$ echo 0 > ./cti_sys0/channels/chan_set
> +
> +Attaches trigout(1) to channel(0), then activates channel(0) generating a
> +set state on cti_sys0.trigout(1)
> +
> +
> +*API operations*
> +
> +   * ``trigin_attach, trigout_attach``: Attach a channel to a trigger signal.
> +   * ``trigin_detach, trigout_detach``: Detach a channel from a trigger signal.
> +   * ``chan_set``: Set the channel - the set state will be propogated around

s/propogated/propagated

This patch will be handled by Jonathan Corbet and as such he needs to be CC'ed
in your next submission. 

> +     the CTM to other connected devices.
> +   * ``chan_clear``: Clear the channel.
> +   * ``chan_pulse``: Set the channel for a single CoreSight clock cycle.
> +   * ``chan_gate_enable``: Write operation sets the CTI gate to propagate
> +     (enable) the channel to other devices. This operation takes a channel
> +     number. CTI gate is enabled for all channels by default at power up. Read
> +     to list the currently enabled channels on the gate.
> +   * ``chan_gate_disable``: Write channel number to disable gate for that
> +     channel.
> +   * ``chan_inuse``: Show the current channels attached to any signal
> +   * ``chan_free``: Show channels with no attached signals.
> +   * ``chan_xtrig_view``: write a channel number to select a channel to view,
> +     read to show the cross triggers programmed for the selected channel.
> +   * ``trig_filter_enable``: Defaults to enabled, disable to allow potentially
> +     dangerous output signals to be set.
> +   * ``trigout_filtered``: Trigger out signals that are prevented from being
> +     set if filtering ``trig_filter_enable`` is enabled. One use is to prevent
> +     accidental ``EDBGREQ`` signals stopping a core.
> +   * ``chan_xtrigs_reset``: Write 1 to clear all channel / trigger programming.
> +     Resets device hardware to default state.
> +
> +e.g.::
> +
> +   .../cti_sys0/channels# echo 2 1 > trigin_attach
> +   .../cti_sys0/channels# echo 2 6 > trigout_attach
> +   .../cti_sys0/channels# cat chan_free
> +   0-1,3
> +   .../cti_sys0/channels# cat chan_inuse
> +   2
> +   .../cti_sys0/channels# echo 2 > chan_xtrigs_view
> +   .../cti_sys0/channels# cat chan_xtrigs_view
> +   [2] IN: 1 OUT: 6
> +   .../cti_sys0/# echo 1 > enable
> +   .../cti_sys0/channels# echo 2 > chan_set
> +   .../cti_sys0/channels# cat ../regs/choutstatus
> +   0x4
> +   .../cti_sys0/channels# cat ../regs/trigoutstatus
> +   0x40
> +   .../cti_sys0/channels# echo 2 > chan_clear
> +   .../cti_sys0/channels# cat ../regs/trigoutstatus
> +   0x0
> +   .../cti_sys0/channels# cat ../regs/trigoutstatus
> +   0x0
> diff --git a/Documentation/trace/coresight/coresight.rst b/Documentation/trace/coresight/coresight.rst
> index a566719f8e7e..108600ee1e12 100644
> --- a/Documentation/trace/coresight/coresight.rst
> +++ b/Documentation/trace/coresight/coresight.rst
> @@ -491,8 +491,21 @@ interface provided for that purpose by the generic STM API::
>  
>  Details on how to use the generic STM API can be found here:- :doc:`../stm` [#second]_.
>  
> +The CTI & CTM Modules
> +---------------------
> +
> +The CTI (Cross Trigger Interface) provides a set of trigger signals between
> +individual CTIs and components, and can propagate these between all CTIs via
> +channels on the CTM (Cross Trigger Matrix).
> +
> +A separate documentation file is provided to explain the use of these devices.
> +(:doc:`coresight-ect`) [#fourth]_.
> +
> +
>  .. [#first] Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
>  
>  .. [#second] Documentation/trace/stm.rst
>  
>  .. [#third] https://github.com/Linaro/perf-opencsd
> +
> +.. [#fourth] Documentation/trace/coresight/coresight-ect.rst
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 14/14] docs: sysfs: coresight: Add sysfs ABI documentation for CTI
  2019-11-19 23:19 ` [PATCH v5 14/14] docs: sysfs: coresight: Add sysfs ABI documentation for CTI Mike Leach
@ 2019-11-27 19:08   ` Mathieu Poirier
  0 siblings, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-27 19:08 UTC (permalink / raw)
  To: Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc, suzuki.poulose

On Tue, Nov 19, 2019 at 11:19:12PM +0000, Mike Leach wrote:
> Add API usage document for sysfs API in CTI driver.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>  .../testing/sysfs-bus-coresight-devices-cti   | 221 ++++++++++++++++++
>  1 file changed, 221 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
> new file mode 100644
> index 000000000000..d867800f567f
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
> @@ -0,0 +1,221 @@
> +What:		/sys/bus/coresight/devices/<cti-name>/enable
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Enable/Disable the CTI hardware.

This will (likely) go in kernel 5.6 that should be released in January 2020.

In your next revision please add yourself as an official reviewer to the
coresight subsystem.  This should be done at the end of the set, in a patch on
its own.

Thanks,
Mathieu

> +
> +What:		/sys/bus/coresight/devices/<cti-name>/ctmid
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) Display the associated CTM ID
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/nr_trigger_cons
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) Number of devices connected to triggers on this CTI
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/name
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) Name of connected device <N>
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/in_signals
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) Input trigger signals from connected device <N>
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/in_types
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) Functional types for the input trigger signals
> +		from connected device <N>
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/out_signals
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) Output trigger signals to connected device <N>
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/triggers<N>/out_types
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) Functional types for the output trigger signals
> +		to connected device <N>
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/inout_sel
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Select the index for inen and outen registers.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/inen
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Read or write the CTIINEN register selected by inout_sel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/outen
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Read or write the CTIOUTEN register selected by inout_sel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/gate
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Read or write CTIGATE register.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/asicctl
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Read or write ASICCTL register.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/intack
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Write the INTACK register.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/appset
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Set CTIAPPSET register to activate channel. Read back to
> +		determine current value of register.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/appclear
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Write APPCLEAR register to deactivate channel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/apppulse
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Write APPPULSE to pulse a channel active for one clock
> +		cycle.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/chinstatus
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) Read current status of channel inputs.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/choutstatus
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) read current status of channel outputs.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/triginstatus
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) read current status of input trigger signals
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/regs/trigoutstatus
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) read current status of output trigger signals.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/trigin_attach
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Attach a CTI input trigger to a CTM channel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/trigin_detach
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Detach a CTI input trigger from a CTM channel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/trigout_attach
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Attach a CTI output trigger to a CTM channel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/trigout_detach
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Detach a CTI output trigger from a CTM channel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_gate_enable
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Enable CTIGATE for single channel (W) or list enabled
> +		channels through the gate (R).
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_gate_disable
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Disable CTIGATE for single channel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_set
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Activate a single channel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_clear
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Deactivate a single channel.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_pulse
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Pulse a single channel - activate for a single clock cycle.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/trigout_filtered
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) List of output triggers filtered across all connections.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/trig_filter_enable
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Enable or disable trigger output signal filtering.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_inuse
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) show channels with at least one attached trigger signal.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_free
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(R) show channels with no attached trigger signals.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_view
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(RW) Write channel number to select a channel to view, read to
> +		see triggers attached to selected channel on this CTI.
> +
> +What:		/sys/bus/coresight/devices/<cti-name>/channels/chan_xtrigs_reset
> +Date:		Jul 2019
> +KernelVersion	5.4
> +Contact:	Mike Leach or Mathieu Poirier
> +Description:	(W) Clear all channel / trigger programming.
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs
  2019-11-19 23:19 ` [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs Mike Leach
  2019-11-27 18:26   ` Suzuki Kuruppassery Poulose
@ 2019-11-28 10:54   ` Suzuki Kuruppassery Poulose
  2019-11-28 17:20     ` Mathieu Poirier
  2019-11-29 12:50     ` Mike Leach
  1 sibling, 2 replies; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-28 10:54 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

On 19/11/2019 23:19, Mike Leach wrote:
> Adds in sysfs programming support for the CTI function register sets.
> Allows direct manipulation of channel / trigger association registers.
> 
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> Signed-off-by: Mike Leach <mike.leach@linaro.org>


> +/*
> + * #define CTI_DEBUG_INTEGRATION_CTRL to enable the access to the integration
> + * control registers. Normally only used to investigate connection data.
> + */

On a second thought, I have some comments on this symbol.

Given that the integration control registers may be useful for people to
find the device connections, I strongly feel that this is provided
via a CONFIG symbol rather than a  debug symbol within the code.

i.e, CONFIG_CTI_DEBUG_INTEGRATION_CTRL, to help the people better.
Codewise this doesn't make much difference, but it certainly makes
it more easier for people to use it.

We have used debug symbols elsewhere in the drivers for pure functional
debugging purposes. However I feel this is case is superior.


Cheers
Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs
  2019-11-28 10:54   ` Suzuki Kuruppassery Poulose
@ 2019-11-28 17:20     ` Mathieu Poirier
  2019-11-28 18:00       ` Suzuki Kuruppassery Poulose
  2019-11-29 12:50     ` Mike Leach
  1 sibling, 1 reply; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-28 17:20 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Mike Leach, Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION

On Thu, 28 Nov 2019 at 03:54, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > Adds in sysfs programming support for the CTI function register sets.
> > Allows direct manipulation of channel / trigger association registers.
> >
> > Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
>
>
> > +/*
> > + * #define CTI_DEBUG_INTEGRATION_CTRL to enable the access to the integration
> > + * control registers. Normally only used to investigate connection data.
> > + */
>
> On a second thought, I have some comments on this symbol.
>
> Given that the integration control registers may be useful for people to
> find the device connections, I strongly feel that this is provided
> via a CONFIG symbol rather than a  debug symbol within the code.

Device connections can be discovered with the dynamic sysfs connection
entries added as part of patch 09.  In cases where that is not
sufficient and people really need to use the integration control
registers they are probably instrumenting the code anyway.

>
> i.e, CONFIG_CTI_DEBUG_INTEGRATION_CTRL, to help the people better.
> Codewise this doesn't make much difference, but it certainly makes
> it more easier for people to use it.

I agree that code-wise it doesn't make much difference but I'm really
not convinced it makes the driver easier to use, and one needs to
recompile their kernel for production systems anyway.

Thanks,
Mathieu

>
> We have used debug symbols elsewhere in the drivers for pure functional
> debugging purposes. However I feel this is case is superior.
>
>
> Cheers
> Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs
  2019-11-28 17:20     ` Mathieu Poirier
@ 2019-11-28 18:00       ` Suzuki Kuruppassery Poulose
  0 siblings, 0 replies; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-28 18:00 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Mike Leach, Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION

Hi Mathieu,

On 28/11/2019 17:20, Mathieu Poirier wrote:
> On Thu, 28 Nov 2019 at 03:54, Suzuki Kuruppassery Poulose
> <suzuki.poulose@arm.com> wrote:
>>
>> On 19/11/2019 23:19, Mike Leach wrote:
>>> Adds in sysfs programming support for the CTI function register sets.
>>> Allows direct manipulation of channel / trigger association registers.
>>>
>>> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>>> Signed-off-by: Mike Leach <mike.leach@linaro.org>
>>
>>
>>> +/*
>>> + * #define CTI_DEBUG_INTEGRATION_CTRL to enable the access to the integration
>>> + * control registers. Normally only used to investigate connection data.
>>> + */
>>
>> On a second thought, I have some comments on this symbol.
>>
>> Given that the integration control registers may be useful for people to
>> find the device connections, I strongly feel that this is provided
>> via a CONFIG symbol rather than a  debug symbol within the code.
> 
> Device connections can be discovered with the dynamic sysfs connection
> entries added as part of patch 09.  In cases where that is not

Yes, that correct. That happens only if the DT/ACPI describes the
connections.

> sufficient and people really need to use the integration control
> registers they are probably instrumenting the code anyway.

In this case given the CTI number of triggers and connections, this
step is to identify the connections in the first place, so that they
can be described in the DT/ACPI. Of course this is not a common
activity, but more of a board bring up activity. Thus, we can't expect
the board bringup engineer to necessarily know how to modify
the driver to get this exposed. Having a Kconfig entry, with
a help text makes this easier for them to avoid fiddling with
the code. Hope this is clearer now.

Cheers
Suzuki


> 
>>
>> i.e, CONFIG_CTI_DEBUG_INTEGRATION_CTRL, to help the people better.
>> Codewise this doesn't make much difference, but it certainly makes
>> it more easier for people to use it.
> 
> I agree that code-wise it doesn't make much difference but I'm really
> not convinced it makes the driver easier to use, and one needs to
> recompile their kernel for production systems anyway.
> 
> Thanks,
> Mathieu
> 
>>
>> We have used debug symbols elsewhere in the drivers for pure functional
>> debugging purposes. However I feel this is case is superior.
>>
>>
>> Cheers
>> Suzuki


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions.
  2019-11-19 23:19 ` [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions Mike Leach
  2019-11-20 19:06   ` Mathieu Poirier
  2019-11-22 23:33   ` Rob Herring
@ 2019-11-28 18:38   ` Suzuki Kuruppassery Poulose
  2019-11-29 13:57     ` Mike Leach
  2 siblings, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-28 18:38 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

Hi Mike,

On 19/11/2019 23:19, Mike Leach wrote:
> Adds new coresight-cti.yaml file describing the bindings required to define
> CTI in the device trees.
> 
> Adds an include file to dt-bindings/arm to define constants describing
> common signal functionality used in CoreSight and generic usage.

The documentation looks really nice and helpful. Some very minor nits
below.

> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>

> ---
>   .../bindings/arm/coresight-cti.yaml           | 303 ++++++++++++++++++
>   .../devicetree/bindings/arm/coresight.txt     |   7 +
>   MAINTAINERS                                   |   2 +
>   include/dt-bindings/arm/coresight-cti-dt.h    |  37 +++
>   4 files changed, 349 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/arm/coresight-cti.yaml
>   create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h
> 
> diff --git a/Documentation/devicetree/bindings/arm/coresight-cti.yaml b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> new file mode 100644
> index 000000000000..882c72f1c798
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> @@ -0,0 +1,303 @@
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright 2019 Linaro Ltd.
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/coresight-cti.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: ARM Coresight Cross Trigger Interface (CTI) device.
> +
> +description: |
> +  The CoreSight Embedded Cross Trigger (ECT) consists of CTI devices connected
> +  to one or more CoreSight components and/or a CPU, with CTIs interconnected in
> +  a star topology via the CTM (which is not programmable). The ECT components

nit: CTM is not expanded anywhere here. For the sake of completeness, 
you may do that here.

i.e, s/"a start topology via the CTM"/"a start topology via the Cross 
Trigger Matrix (CTM)"/


> +  are not part of the trace generation data path and are thus not part of the
> +  CoreSight graph described in the general CoreSight bindings file
> +  coresight.txt.
> +
> +  The CTI component properties define the connections between the individual
> +  CTI and the components it is directly connected to, consisting of input and
> +  output hardware trigger signals. CTIs can have a maximum number of input and
> +  output hardware trigger signals (8 each for v1 CTI, 32 each for v2 CTI). The
> +  number is defined at design time, the maximum of each defined in the DEVID
> +  register.
> +
> +  CTIs are interconnected in a star topology via the CTM, using a number of
> +  programmable channels usually 4, but again implementation defined and

nit: "programmable channels, usually 4, but..." ?

> +  described in the DEVID register. The star topology is not required to be
> +  described in the bindings as the actual connections are software
> +  programmable.
> +
> +  In general the connections between CTI and components via the trigger signals
> +  are implementation defined, other than when v8 core and ETM is present.

nite: are implementation defined, *except when they are connected to an 
Arm v8 compatible CPU or an ETM* ?


> +  The v8 architecture defines the required signal connections between CPU core

nit: "The Arm v8"

> +  and CTI, and ETM and CTI, if the ETM if present.
> +
> +  When only minimal information is available for the CTI trigger connections,
> +  then a minimal driver binding can be declare with no explicit trigger
> +  signals. This will result in the using the DEVID register to set the
> +  input and output triggers and channels in use. Any user / client
> +  application will require additional information on the connections
> +  between the CTI and other components for correct operation. This minimal
> +  binding may be used when using the Integration Control registers to
> +  discover connections between CTI and other CoreSight components,

How about "When the CTI trigger connection information is unavailable,
the driver detects the number of triggers and channels from the DEVID
register and makes them available. The Integration Control registers
can be then used to discover the connections for this CTI device
to other CoreSight components".

Since we recommend the use of the "Integration Control registers", which
is not normally available unless you play around the code, it will be a
good idea to metion, what the user needs to do to make the registers
available. (One more reason to use the CONFIG symbol, makes that
easier.)


> +
> +  Certain triggers between CoreSight devices and the CTI have specific types
> +  and usages. These can be defined along with the signal indexes with the
> +  constants defined in <dt-bindings/arm/coresight-cti-dt.h>
> +
> +  For example a CTI connected to a core will usually have a DBGREQ signal. This
> +  is defined in the binding as type PE_EDBGREQ. These types will appear in an
> +  optional array alongside the signal indexes. Omitting types will default all
> +  signals to GEN_IO.
> +
> +  Note that some hardware trigger signals can be connected to non-CoreSight
> +  components (e.g. UART etc) depending on hardware implementation.
> +
> +maintainers:
> +  - Mike Leach <mike.leach@linaro.org>
> +
> +allOf:
> +  - $ref: /schemas/arm/primecell.yaml#
> +
> +# Need a custom select here or 'arm,primecell' will match on lots of nodes
> +select:
> +  properties:
> +    compatible:
> +      contains:
> +        enum:
> +          - arm,coresight-cti
> +  required:
> +    - compatible
> +
> +properties:
> +  $nodename:
> +    pattern: "^cti(@[0-9a-f,]+)*$"
> +  compatible:
> +    items:
> +      - const: arm,coresight-cti
> +      - const: arm,primecell
> +
> +  reg:
> +    items:
> +      - description: device programming registers
> +
> +  arm,cti-v8-arch:

If possible, please could we make this :

"arm,cti-arm-v8-architected"

to be more meaning ful ?

> +    type: boolean
> +    description:
> +      This CTI follows the v8 architecturally mandated layout for a CTI.
> +      Bindings declaring this must declare a cpu, and optionally a single
> +      arm,cs-dev-assoc may be present to define an attached ETM. No additional
> +      trig-conns nodes are permitted. The driver will build a connection model
> +      according to architectural requirements. This will include a filter on
> +      the CPU dbgreq signal as described above.
> +
> +  cpu:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description: Handle to cpu this device is associated with.
> +
> +  arm,cti-ctm-id:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/uint32
> +    description:
> +      Defines the CTM this CTI is connected to, in large systems with multiple
> +      separate CTI/CTM nets. Typically multi-socket systems where the CTM is
> +      propagated between sockets.
> +
> +  arm,cs-dev-assoc:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description:
> +      defines a phandle reference to an associated CoreSight trace device.
> +      When the associated trace device is enabled, then the respective CTI
> +      will be enabled. Use in a trig-conns node, or in CTI base node when
> +      arm,cti-v8-arch present. If the associated device has not been registered
> +      then the node name will be stored as the connection name for later
> +      resolution. If the associated device is not a CoreSight device or not
> +      registered then the node name will remain the connection name and
> +      automatic enabling will not occur.
> +
> +patternProperties:
> +  '^trig_conns@[0-9]+$':

I understand these bindings have been around for quite long and is too
late to make any changes. So, feel free to ignore this suggestion below
and I am perfectly fine with it.

--- Begin silly comments Or Skip to DONE ----

Could we make the property names a bit more obvious ? Since they are 
supposed to be written by other people (unlike our variable names), it
always makes sense to have expanded, meaningful names:

s/trig_conns@/triggers@ ?

s/arm,trig-{in,out}-sigs/arm,cti-{in,out}-triggers
s/arm,trig-{in,out}-types/arm,cti-{in,out}-trigger-types

"arm,trig-xxx" property name doesn't really imply that it is for cti.
So, the above changes makes it explicit and more reader friendly.

> +    type: object
> +    description:
> +      A trigger connections child node which describes the trigger signals
> +      between this CTI and another hardware device. This device may be a CPU,
> +      CoreSight device, any other hardware device or simple external IO lines.
> +      The connection may have both input and output triggers, or only one or the
> +      other.
> +
> +    properties:
> +
> +      arm,trig-in-sigs:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of CTI trigger in signal numbers in use by a trig-conns node.
> +
> +      arm,trig-in-types:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of constants representing the types for the CTI trigger in
> +          signals. Types in this array match to the corresponding signal in the
> +          arm,trig-in-sigs array. If the -types array is smaller, or omitted
> +          completely, then the types will default to GEN_IO.
> +
> +      arm,trig-out-sigs:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of CTI trigger out signal numbers in use by a trig-conns node.
> +
> +      arm,trig-out-types:
> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of constants representing the types for the CTI trigger out
> +          signals. Types in this array match to the corresponding signal
> +          in the arm,trig-out-sigs array. If the "-types" array is smaller,
> +          or omitted completely, then the types will default to GEN_IO.
> +
> +      arm,trig-filters:

arm,cti-trigger-filters ?

> +        allOf:
> +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> +        minItems: 1
> +        maxItems: 32
> +        description:
> +          List of CTI trigger out signals that will be blocked from becoming
> +          active, unless filtering is disabled on the driver.
> +
> +      arm,trig-conn-name:

arm,cti-trigger-name ?


--- DONE or End of silly comments ---

> +  # Implementation defined CTI - CPU + ETM connections explicitly defined..
> +  # Shows use of type constants from dt-bindings/arm/coresight-cti-dt.h
> +  - |
> +    #include <dt-bindings/arm/coresight-cti-dt.h>
> +
> +    cti@858000 {
> +      compatible = "arm,coresight-cti", "arm,primecell";
> +      reg = <0x858000 0x1000>;
> +
> +      clocks = <&soc_smc50mhz>;
> +      clock-names = "apb_pclk";
> +
> +      arm,cti-ctm-id = <1>;
> +
> +      trig-conns@0 {
> +            arm,trig-in-sigs = <4 5 6 7>;
> +            arm,trig-in-types = <ETM_EXTOUT
> +                                 ETM_EXTOUT
> +                                 ETM_EXTOUT
> +                                 ETM_EXTOUT>;
> +            arm,trig-out-sigs = <4 5 6 7>;
> +            arm,trig-out-types = <ETM_EXTIN
> +                                  ETM_EXTIN
> +                                  ETM_EXTIN
> +                                  ETM_EXTIN>;
> +            arm,cs-dev-assoc = <&etm0>;
> +      };
> +
> +      trig-conns@1 {
> +            cpu = <&CPU0>;
> +            arm,trig-in-sigs = <0 1>;
> +            arm,trig-in-types = <PE_DBGTRIGGER
> +                                 PE_PMUIRQ>;
> +            arm,trig-out-sigs=<0 1 2 >;
> +            arm,trig-out-types = <PE_EDBGREQ
> +                                  PE_DBGRESTART
> +                                  PE_CTIIRQ>;
> +
> +            arm,trig-filters = <0>;
> +      };
> +    };
> +  # Implementation defined CTI - none CoreSight component connections.

nit: s/none/non ?

Rest looks fine to me.

Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI
  2019-11-19 23:19 ` [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI Mike Leach
  2019-11-25 19:00   ` Mathieu Poirier
@ 2019-11-29 11:33   ` Suzuki Kuruppassery Poulose
  2019-12-03 10:59     ` Mike Leach
  1 sibling, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-29 11:33 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

On 19/11/2019 23:19, Mike Leach wrote:
> The v8 architecture defines the relationship between a PE, its optional ETM
> and a CTI. Unlike non-architectural CTIs which are implementation defined,
> this has a fixed set of connections which can therefore be represented as a
> simple tag in the device tree.
> 
> This patch defines the tags needed to create an entry for this PE/ETM/CTI
> relationship, and provides functionality to implement the connection model
> in the CTI driver.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>   .../coresight/coresight-cti-platform.c        | 205 ++++++++++++++++++
>   1 file changed, 205 insertions(+)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
> index 665be86c585d..790dd30b85f5 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-platform.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
> @@ -3,10 +3,208 @@
>    * Copyright (c) 2019, The Linaro Limited. All rights reserved.
>    */
>   
> +#include <dt-bindings/arm/coresight-cti-dt.h>
>   #include <linux/of.h>
>   
>   #include "coresight-cti.h"
>   
> +/* Number of CTI signals in the v8 architecturally defined connection */
> +#define NR_V8PE_IN_SIGS		2
> +#define NR_V8PE_OUT_SIGS	3
> +#define NR_V8ETM_INOUT_SIGS	4
> +
> +/* CTI device tree connection property keywords */
> +#define CTI_DT_V8ARCH		"arm,cti-v8-arch"
> +#define CTI_DT_CSDEV_ASSOC	"arm,cs-dev-assoc"
> +
> +/*
> + * Find a registered coresight device from a device fwnode.
> + * The node info is associated with the AMBA parent, but the
> + * csdev keeps a copy so iterate round the coresight bus to
> + * find the device.
> + */
> +static struct coresight_device *
> +cti_get_assoc_csdev_by_fwnode(struct fwnode_handle *r_fwnode)

To be frank this has nothing to do with the CTI and is in a way
a good candidate for a CoreSight generic function. We do similar
stuff in coresight_fixup_device_conns(). So this could be :

struct coresight_device *
coresight_find_device_by_fwnode(const struct fwnode_handle *fwnode)

> +{
> +	struct device *dev;
> +	struct coresight_device *csdev = NULL;
> +
> +	dev = bus_find_device_by_fwnode(&coresight_bustype, r_fwnode);
> +	if (dev) {
> +		csdev = to_coresight_device(dev);
> +		put_device(dev);
> +	}
> +	return csdev;
> +}
> +

And used in coresight_fixup_conns().

> +#ifdef CONFIG_OF
> +/*
> + * CTI can be bound to a CPU, or a system device.
> + * CPU can be declared at the device top level or in a connections node
> + * so need to check relative to node not device.
> + */
> +static int of_cti_get_cpu_at_node(const struct device_node *node)
> +{
> +	int cpu;
> +	struct device_node *dn;
> +
> +	if (node == NULL)
> +		return -1;
> +
> +	dn = of_parse_phandle(node, "cpu", 0);
> +	/* CTI affinity defaults to no cpu */
> +	if (!dn)
> +		return -1;
> +	cpu = of_cpu_node_to_id(dn);
> +	of_node_put(dn);
> +
> +	/* No Affinity  if no cpu nodes are found */
> +	return (cpu < 0) ? -1 : cpu;
> +}
> +
> +static const char *of_cti_get_node_name(const struct device_node *node)
> +{
> +	if (node)
> +		return node->full_name;
> +	return "unknown";
> +}
> +#else
> +static int of_cti_get_cpu_at_node(const struct device_node *node)
> +{
> +	return -1;
> +}
> +
> +static const char *of_cti_get_node_name(const struct device_node *node)
> +{
> +	return "unknown";
> +}
> +#endif
> +
> +static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
> +{

You may simply reuse coresight_get_cpu() below, instead of adding this
duplicate set of functions. See below.


> +static int cti_plat_create_v8_etm_connection(struct device *dev,
> +					     struct cti_drvdata *drvdata)
> +{
> +	int ret = -ENOMEM, i;
> +	struct fwnode_handle *root_fwnode, *cs_fwnode;
> +	const char *assoc_name = NULL;
> +	struct coresight_device *csdev;
> +	struct cti_trig_con *tc = NULL;
> +
> +	root_fwnode = dev_fwnode(dev);
> +	if (IS_ERR_OR_NULL(root_fwnode))
> +		return -EINVAL;
> +
> +	/* Can optionally have an etm node - return if not  */
> +	cs_fwnode = fwnode_find_reference(root_fwnode, CTI_DT_CSDEV_ASSOC, 0);
> +	if (IS_ERR_OR_NULL(cs_fwnode))
> +		return 0;
> +
> +	/* allocate memory */
> +	tc = cti_allocate_trig_con(dev, NR_V8ETM_INOUT_SIGS,
> +				   NR_V8ETM_INOUT_SIGS);
> +	if (!tc)
> +		goto create_v8_etm_out;
> +
> +	/* build connection data */
> +	tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */
> +	tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */
> +
> +	/*
> +	 * The EXTOUT type signals from the ETM are connected to a set of input
> +	 * triggers on the CTI, the EXTIN being connected to output triggers.
> +	 */
> +	for (i = 0; i < NR_V8ETM_INOUT_SIGS; i++) {
> +		tc->con_in->sig_types[i] = ETM_EXTOUT;
> +		tc->con_out->sig_types[i] = ETM_EXTIN;
> +	}
> +
> +	/*
> +	 * We look to see if the ETM coresight device associated with this
> +	 * handle has been registered with the system - i.e. probed before
> +	 * this CTI. If so csdev will be non NULL and we can use the device
> +	 * name and pass the csdev to the connection entry function where
> +	 * the association will be recorded.
> +	 * If not, then simply record the name in the connection data, the
> +	 * probing of the ETM will call into the CTI driver API to update the
> +	 * association then.
> +	 */
> +	csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
> +	if (csdev)
> +		assoc_name = dev_name(&csdev->dev);

Does it make sense to defer the probing until the ETM device  turn up ?
Its fine either way.

> +	else
> +		assoc_name = cti_plat_get_node_name(cs_fwnode);
> +	ret = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name);
> +
> +create_v8_etm_out:
> +	fwnode_handle_put(cs_fwnode);
> +	return ret;
> +}
> +
> +/*
> + * Create an architecturally defined v8 connection
> + * must have a cpu, can have an ETM.
> + */
> +static int cti_plat_create_v8_connections(struct device *dev,
> +					  struct cti_drvdata *drvdata)
> +{
> +	struct cti_device *cti_dev = &drvdata->ctidev;
> +	struct cti_trig_con *tc = NULL;
> +	int cpuid = 0;
> +	char cpu_name_str[16];
> +	int ret = -ENOMEM;
> +
> +	/* Must have a cpu node */
> +	cpuid = cti_plat_get_cpu_at_node(dev_fwnode(dev));

Could we reuse coresight_get_cpu(dev) instead ? I understand that the
ACPI bindings have not been defined and it may be slightly different
from what we have now for the ETMs (i.e, ETM node as child of the CPU
node). But I don't see why we can't force it for the CTIs either.
In the worst case, you could still reuse the of_coresgith_get_cpu(dev)
instead of writing your own for the OF case.


> +	if (cpuid < 0) {
> +		dev_warn(dev, "CTI v8 DT binding no cpu\n");

This may be better off without mentioning the DT. e.g,

"CTI Arm v8 architected connection: missing CPU\n"

	
> +		return -EINVAL;
> +	}
> +	cti_dev->cpu = cpuid;
> +
> +	/* Allocate the v8 cpu connection memory */
> +	tc = cti_allocate_trig_con(dev, NR_V8PE_IN_SIGS, NR_V8PE_OUT_SIGS);
> +	if (!tc)
> +		goto of_create_v8_out;
> +
> +	/* Set the v8 PE CTI connection data */
> +	tc->con_in->used_mask = 0x3; /* sigs <0 1> */
> +	tc->con_in->sig_types[0] = PE_DBGTRIGGER;
> +	tc->con_in->sig_types[1] = PE_PMUIRQ;
> +	tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */
> +	tc->con_out->sig_types[0] = PE_EDBGREQ;
> +	tc->con_out->sig_types[1] = PE_DBGRESTART;
> +	tc->con_out->sig_types[2] = PE_CTIIRQ;
> +	scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid);
> +
> +	ret = cti_add_connection_entry(dev, drvdata, tc, NULL, cpu_name_str);
> +	if (ret)
> +		goto of_create_v8_out;
> +
> +	/* Create the v8 ETM associated connection */
> +	ret = cti_plat_create_v8_etm_connection(dev, drvdata);
> +	if (ret)
> +		goto of_create_v8_out;
> +
> +	/* filter pe_edbgreq - PE trigout sig <0> */
> +	drvdata->config.trig_out_filter |= 0x1;
> +
> +of_create_v8_out:
> +	return ret;
> +}
> +
>   /* get the hardware configuration & connection data. */
>   int cti_plat_get_hw_data(struct device *dev,
>   			 struct cti_drvdata *drvdata)
> @@ -14,6 +212,13 @@ int cti_plat_get_hw_data(struct device *dev,
>   	int rc = 0;
>   	struct cti_device *cti_dev = &drvdata->ctidev;
>   
> +	/* check for a v8 architectural CTI device */
minor nit: Check for Arm v8 architected CTI connection ?

> +	if (device_property_read_bool(dev, CTI_DT_V8ARCH)) {
> +		rc = cti_plat_create_v8_connections(dev, drvdata);
> +		if (rc)
> +			return rc;
> +	}
> +
>   	/* if no connections, just add a single default based on max IN-OUT */
>   	if (cti_dev->nr_trig_con == 0)
>   		rc = cti_add_default_connection(dev, drvdata);
> 


Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 01/14] coresight: cti: Initial CoreSight CTI Driver
  2019-11-21 20:21   ` Mathieu Poirier
@ 2019-11-29 12:05     ` Mike Leach
  2019-12-03 16:53       ` Mathieu Poirier
  0 siblings, 1 reply; 62+ messages in thread
From: Mike Leach @ 2019-11-29 12:05 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Suzuki K. Poulose

Hi Mathieu,

On Thu, 21 Nov 2019 at 20:21, Mathieu Poirier
<mathieu.poirier@linaro.org> wrote:
>
> On Tue, Nov 19, 2019 at 11:18:59PM +0000, Mike Leach wrote:
> > This introduces a baseline CTI driver and associated configuration files.
> >
> > Uses the platform agnostic naming standard for CoreSight devices, along
> > with a generic platform probing method that currently supports device
> > tree descriptions, but allows for the ACPI bindings to be added once these
> > have been defined for the CTI devices.
> >
> > Driver will probe for the device on the AMBA bus, and load the CTI driver
> > on CoreSight ID match to CTI IDs in tables.
> >
> > Initial sysfs support for enable / disable provided.
> >
> > Default CTI interconnection data is generated based on hardware
> > register signal counts, with no additional connection information.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >  drivers/hwtracing/coresight/Kconfig           |  12 +
> >  drivers/hwtracing/coresight/Makefile          |   3 +
> >  .../coresight/coresight-cti-platform.c        |  53 +++
> >  .../hwtracing/coresight/coresight-cti-sysfs.c |  72 +++
> >  drivers/hwtracing/coresight/coresight-cti.c   | 448 ++++++++++++++++++
> >  drivers/hwtracing/coresight/coresight-cti.h   | 186 ++++++++
> >  drivers/hwtracing/coresight/coresight.c       |   3 +
> >  include/linux/coresight.h                     |  23 +
> >  8 files changed, 800 insertions(+)
> >  create mode 100644 drivers/hwtracing/coresight/coresight-cti-platform.c
> >  create mode 100644 drivers/hwtracing/coresight/coresight-cti-sysfs.c
> >  create mode 100644 drivers/hwtracing/coresight/coresight-cti.c
> >  create mode 100644 drivers/hwtracing/coresight/coresight-cti.h
> >
> > diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> > index 6ff30e25af55..45d3822c8c8c 100644
> > --- a/drivers/hwtracing/coresight/Kconfig
> > +++ b/drivers/hwtracing/coresight/Kconfig
> > @@ -110,4 +110,16 @@ 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 (CTI) driver"
> > +     depends on ARM || ARM64
> > +     help
> > +       This driver provides support for CoreSight CTI and CTM components.
> > +       These provide hardware triggering events between CoreSight trace
> > +       source and sink components. These can be used to halt trace or
> > +       inject events into the trace stream. CTI also provides a software
> > +       control to trigger the same halt events. This can provide fast trace
> > +       halt compared to disabling sources and sinks normally in driver
> > +       software.
> > +
> >  endif
> > diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> > index 3c0ac421e211..0e3e72f0f510 100644
> > --- a/drivers/hwtracing/coresight/Makefile
> > +++ b/drivers/hwtracing/coresight/Makefile
> > @@ -17,3 +17,6 @@ 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 \
> > +                             coresight-cti-platform.o \
> > +                             coresight-cti-sysfs.o
> > diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
> > new file mode 100644
> > index 000000000000..665be86c585d
> > --- /dev/null
> > +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
> > @@ -0,0 +1,53 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2019, The Linaro Limited. All rights reserved.
> > + */
> > +
> > +#include <linux/of.h>
> > +
> > +#include "coresight-cti.h"
> > +
> > +/* get the hardware configuration & connection data. */
> > +int cti_plat_get_hw_data(struct device *dev,
> > +                      struct cti_drvdata *drvdata)
> > +{
> > +     int rc = 0;
> > +     struct cti_device *cti_dev = &drvdata->ctidev;
> > +
> > +     /* if no connections, just add a single default based on max IN-OUT */
> > +     if (cti_dev->nr_trig_con == 0)
> > +             rc = cti_add_default_connection(dev, drvdata);
> > +     return rc;
> > +}
> > +
> > +struct coresight_platform_data *
> > +coresight_cti_get_platform_data(struct device *dev)
> > +{
> > +     int ret = -ENOENT;
> > +     struct coresight_platform_data *pdata = NULL;
> > +     struct fwnode_handle *fwnode = dev_fwnode(dev);
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev);
> > +
> > +     if (IS_ERR_OR_NULL(fwnode))
> > +             goto error;
> > +
> > +     /*
> > +      * Alloc platform data but leave it zero init. CTI does not use the
> > +      * same connection infrastructuree as trace path components but an
> > +      * empty struct enables us to use the standard coresight component
> > +      * registration code.
> > +      */
> > +     pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> > +     if (!pdata) {
> > +             ret = -ENOMEM;
> > +             goto error;
> > +     }
> > +
> > +     /* get some CTI specifics */
> > +     ret = cti_plat_get_hw_data(dev, drvdata);
> > +
> > +     if (!ret)
> > +             return pdata;
> > +error:
> > +     return ERR_PTR(ret);
> > +}
> > diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > new file mode 100644
> > index 000000000000..a832b8c6b866
> > --- /dev/null
> > +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > @@ -0,0 +1,72 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2019 Linaro Limited, All rights reserved.
> > + * Author: Mike Leach <mike.leach@linaro.org>
> > + */
> > +
> > +#include <linux/coresight.h>
> > +
> > +#include "coresight-cti.h"
> > +
> > +/* basic attributes */
> > +static ssize_t enable_show(struct device *dev,
> > +                        struct device_attribute *attr,
> > +                        char *buf)
> > +{
> > +     int enable_req;
> > +     bool enabled, powered;
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +     ssize_t size = 0;
> > +
> > +     enable_req = atomic_read(&drvdata->config.enable_req_count);
> > +     spin_lock(&drvdata->spinlock);
> > +     powered = drvdata->config.hw_powered;
> > +     enabled = drvdata->config.hw_enabled;
> > +     spin_unlock(&drvdata->spinlock);
> > +
> > +     if (powered) {
> > +             size = scnprintf(buf, PAGE_SIZE, "cti %s; powered;\n",
> > +                              enabled ? "enabled" : "disabled");
> > +     } else {
> > +             size = scnprintf(buf, PAGE_SIZE, "cti %s; unpowered;\n",
> > +                              enable_req ? "enable req" : "disabled");
> > +     }
> > +     return size;
> > +}
> > +
> > +static ssize_t enable_store(struct device *dev,
> > +                         struct device_attribute *attr,
> > +                         const char *buf, size_t size)
> > +{
> > +     int ret = 0;
> > +     unsigned long val;
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +
> > +     ret = kstrtoul(buf, 0, &val);
> > +     if (ret)
> > +             return ret;
> > +
> > +     if (val)
> > +             ret = cti_enable(drvdata->csdev);
> > +     else
> > +             ret = cti_disable(drvdata->csdev);
> > +     if (ret)
> > +             return ret;
> > +     return size;
> > +}
> > +static DEVICE_ATTR_RW(enable);
> > +
> > +/* attribute and group sysfs tables. */
> > +static struct attribute *coresight_cti_attrs[] = {
> > +     &dev_attr_enable.attr,
> > +     NULL,
> > +};
> > +
> > +static const struct attribute_group coresight_cti_group = {
> > +     .attrs = coresight_cti_attrs,
> > +};
> > +
> > +const struct attribute_group *coresight_cti_groups[] = {
> > +     &coresight_cti_group,
> > +     NULL,
> > +};
> > diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> > new file mode 100644
> > index 000000000000..7ae48bf62d17
> > --- /dev/null
> > +++ b/drivers/hwtracing/coresight/coresight-cti.c
> > @@ -0,0 +1,448 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2018 Linaro Limited, All rights reserved.
> > + * Author: Mike Leach <mike.leach@linaro.org>
> > + */
> > +
> > +#include "coresight-cti.h"
> > +
> > +/**
> > + * CTI devices can be associated with a PE, or be connected to CoreSight
> > + * hardware. We have a list of all CTIs irrespective of CPU bound or
> > + * otherwise.
> > + *
> > + * We assume that the non-CPU CTIs are always powered as we do with sinks etc.
> > + *
> > + * We leave the client to figure out if all the CTIs are interconnected with
> > + * the same CTM, in general this is the case but does not always have to be.
> > + */
> > +
> > +/* net of CTI devices connected via CTM */
> > +LIST_HEAD(ect_net);
> > +
> > +/* protect the list */
> > +static DEFINE_MUTEX(ect_mutex);
> > +
> > +#define csdev_to_cti_drvdata(csdev)  \
> > +     dev_get_drvdata(csdev->dev.parent)
> > +
> > +/*
> > + * CTI naming. CTI bound to cores will have the name cti_cpu<N> where
> > + * N is the CPU ID. System CTIs will have the name cti_sys<I> where I
> > + * is an index allocated by order of discovery.
> > + *
> > + * CTI device name list - for CTI not bound to cores.
> > + */
> > +DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys");
> > +
> > +/* write set of regs to hardware - call with spinlock claimed */
> > +void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_config *config = &drvdata->config;
> > +     int i;
> > +
> > +     CS_UNLOCK(drvdata->base);
> > +
> > +     /* disable CTI before writing registers */
> > +     writel_relaxed(0, drvdata->base + CTICONTROL);
> > +
> > +     /* write the CTI trigger registers */
> > +     for (i = 0; i < config->nr_trig_max; i++) {
> > +             writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i));
> > +             writel_relaxed(config->ctiouten[i],
> > +                            drvdata->base + CTIOUTEN(i));
> > +     }
> > +
> > +     /* other regs */
> > +     writel_relaxed(config->ctigate, drvdata->base + CTIGATE);
> > +     writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
> > +     writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);
> > +
> > +     /* re-enable CTI */
> > +     writel_relaxed(1, drvdata->base + CTICONTROL);
> > +
> > +     CS_LOCK(drvdata->base);
> > +}
> > +
> > +static void cti_enable_hw_smp_call(void *info)
> > +{
> > +     struct cti_drvdata *drvdata = info;
> > +
> > +     cti_write_all_hw_regs(drvdata);
> > +}
> > +
> > +/* write regs to hardware and enable */
> > +static int cti_enable_hw(struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_config *config = &drvdata->config;
> > +     struct device *dev = &drvdata->csdev->dev;
> > +     int rc = 0;
> > +
> > +     pm_runtime_get_sync(dev->parent);
> > +     spin_lock(&drvdata->spinlock);
> > +
> > +     /* no need to do anything if enabled or unpowered*/
> > +     if (config->hw_enabled || !config->hw_powered)
> > +             goto cti_state_unchanged;
> > +
> > +     /* claim the device */
> > +     rc = coresight_claim_device(drvdata->base);
> > +     if (rc)
> > +             goto cti_err_not_enabled;
> > +
> > +     if (drvdata->ctidev.cpu >= 0) {
> > +             rc = smp_call_function_single(drvdata->ctidev.cpu,
> > +                                           cti_enable_hw_smp_call,
> > +                                           drvdata, 1);
> > +             if (rc)
> > +                     goto cti_err_not_enabled;
> > +     } else {
> > +             cti_write_all_hw_regs(drvdata);
> > +     }
> > +
> > +     config->hw_enabled = true;
> > +     atomic_inc(&drvdata->config.enable_req_count);
> > +     spin_unlock(&drvdata->spinlock);
> > +     return rc;
> > +
> > +cti_state_unchanged:
> > +     atomic_inc(&drvdata->config.enable_req_count);
> > +
> > +     /* cannot enable due to error */
> > +cti_err_not_enabled:
> > +     spin_unlock(&drvdata->spinlock);
> > +     pm_runtime_put(dev->parent);
> > +     return rc;
> > +}
> > +
> > +/* disable hardware */
> > +static int cti_disable_hw(struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_config *config = &drvdata->config;
> > +     struct device *dev = &drvdata->csdev->dev;
> > +
> > +     spin_lock(&drvdata->spinlock);
> > +
> > +     /* check refcount - disable on 0 */
> > +     if (atomic_dec_return(&drvdata->config.enable_req_count) > 0)
> > +             goto cti_not_disabled;
> > +
> > +     /* no need to do anything if disabled or cpu unpowered */
> > +     if (!config->hw_enabled || !config->hw_powered)
> > +             goto cti_not_disabled;
> > +
> > +     CS_UNLOCK(drvdata->base);
> > +
> > +     /* disable CTI */
> > +     writel_relaxed(0, drvdata->base + CTICONTROL);
> > +     config->hw_enabled = false;
> > +
> > +     coresight_disclaim_device_unlocked(drvdata->base);
> > +     CS_LOCK(drvdata->base);
> > +     spin_unlock(&drvdata->spinlock);
> > +     pm_runtime_put(dev);
> > +     return 0;
> > +
> > +     /* not disabled this call */
> > +cti_not_disabled:
> > +     spin_unlock(&drvdata->spinlock);
> > +     return 0;
> > +}
> > +
> > +/*
> > + * Look at the HW DEVID register for some of the HW settings.
> > + * DEVID[15:8] - max number of in / out triggers.
> > + */
> > +#define CTI_DEVID_MAXTRIGS(devid_val) (int)((devid_val & 0xFF00) >> 8)
> > +
> > +/* DEVID[19:16] - number of CTM channels */
> > +#define CTI_DEVID_CTMCHANNELS(devid_val) (int)((devid_val & 0xF0000) >> 16)
> > +
> > +static void cti_set_default_config(struct device *dev,
> > +                                struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_config *config = &drvdata->config;
> > +     u32 devid;
> > +
> > +     devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
> > +     config->nr_trig_max = CTI_DEVID_MAXTRIGS(devid);
> > +
> > +     /*
> > +      * no current hardware should exceed this, but protect the driver
> > +      * in case of fault / out of spec hw
> > +      */
> > +     if (config->nr_trig_max > CTIINOUTEN_MAX) {
> > +             dev_warn_once(dev,
> > +                     "Limiting HW MaxTrig value(%d) to driver max(%d)\n",
> > +                     config->nr_trig_max, CTIINOUTEN_MAX);
> > +             config->nr_trig_max = CTIINOUTEN_MAX;
> > +     }
> > +
> > +     config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid);
> > +
> > +     /* Most regs default to 0 as zalloc'ed except...*/
> > +     config->trig_filter_enable = true;
> > +     config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
> > +     atomic_set(&config->enable_req_count, 0);
> > +}
> > +
> > +/*
> > + * Add a connection entry to the list of connections for this
> > + * CTI device.
> > + */
> > +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
> > +                          struct cti_trig_con *tc,
> > +                          struct coresight_device *csdev,
> > +                          const char *assoc_dev_name)
> > +{
> > +     struct cti_device *cti_dev = &drvdata->ctidev;
> > +
> > +     tc->con_dev = csdev;
> > +     /*
> > +      * Prefer actual associated CS device dev name to supplied value -
> > +      * which is likely to be node name / other conn name.
> > +      */
> > +     if (csdev)
> > +             tc->con_dev_name = devm_kstrdup(dev,
> > +                                             dev_name(&csdev->dev),
> > +                                             GFP_KERNEL);
> > +     else if (assoc_dev_name != NULL)
> > +             tc->con_dev_name = devm_kstrdup(dev,
> > +                                             assoc_dev_name, GFP_KERNEL);
> > +     list_add_tail(&tc->node, &cti_dev->trig_cons);
> > +     cti_dev->nr_trig_con++;
> > +
> > +     /* add connection usage bit info to overall info */
> > +     drvdata->config.trig_in_use |= tc->con_in->used_mask;
> > +     drvdata->config.trig_out_use |= tc->con_out->used_mask;
> > +
> > +     return 0;
> > +}
> > +
> > +/* create a trigger connection with appropriately sized signal groups */
> > +struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
> > +                                        int out_sigs)
> > +{
> > +     struct cti_trig_con *tc = NULL;
> > +     struct cti_trig_grp *in = NULL, *out = NULL;
> > +
> > +     tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL);
> > +     if (!tc)
> > +             return tc;
> > +
> > +     in = devm_kzalloc(dev,
> > +                       offsetof(struct cti_trig_grp, sig_types[in_sigs]),
> > +                       GFP_KERNEL);
> > +     if (!in)
> > +             return NULL;
> > +
> > +     out = devm_kzalloc(dev,
> > +                        offsetof(struct cti_trig_grp, sig_types[out_sigs]),
> > +                        GFP_KERNEL);
> > +     if (!out)
> > +             return NULL;
> > +
> > +     tc->con_in = in;
> > +     tc->con_out = out;
> > +     tc->con_in->nr_sigs = in_sigs;
> > +     tc->con_out->nr_sigs = out_sigs;
> > +     return tc;
> > +}
> > +
> > +/*
> > + * Add a default connection if nothing else is specified.
> > + * single connection based on max in/out info, no assoc device
> > + */
> > +int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
> > +{
> > +     int ret = 0;
> > +     int n_trigs = drvdata->config.nr_trig_max;
> > +     u32 n_trig_mask = GENMASK(n_trigs - 1, 0);
> > +     struct cti_trig_con *tc = NULL;
> > +
> > +     /*
> > +      * Assume max trigs for in and out,
> > +      * all used, default sig types allocated
> > +      */
> > +     tc = cti_allocate_trig_con(dev, n_trigs, n_trigs);
> > +     if (!tc)
> > +             return -ENOMEM;
> > +
> > +     tc->con_in->used_mask = n_trig_mask;
> > +     tc->con_out->used_mask = n_trig_mask;
> > +     ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default");
> > +     return ret;
> > +}
> > +
> > +/** cti ect operations **/
> > +int cti_enable(struct coresight_device *csdev)
> > +{
> > +     struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> > +
> > +     /* enable hardware with refcount */
> > +     return cti_enable_hw(drvdata);
> > +}
> > +
> > +int cti_disable(struct coresight_device *csdev)
> > +{
> > +     struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> > +
> > +     /* disable hardware with refcount */
> > +     return cti_disable_hw(drvdata);
> > +}
> > +
> > +const struct coresight_ops_ect cti_ops_ect = {
> > +     .enable = cti_enable,
> > +     .disable = cti_disable,
> > +};
> > +
> > +const struct coresight_ops cti_ops = {
> > +     .ect_ops = &cti_ops_ect,
> > +};
> > +
> > +/*
> > + * Free up CTI specific resources
> > + * called by dev->release, need to call down to underlying csdev release.
> > + */
> > +static void cti_device_release(struct device *dev)
> > +{
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +     struct cti_drvdata *ect_item, *ect_tmp;
> > +
> > +     mutex_lock(&ect_mutex);
> > +
> > +     /* remove from the list */
> > +     list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
> > +             if (ect_item == drvdata) {
> > +                     list_del(&ect_item->node);
> > +                     break;
> > +             }
> > +     }
> > +     mutex_unlock(&ect_mutex);
> > +
> > +     if (drvdata->csdev_release)
> > +             drvdata->csdev_release(dev);
> > +}
> > +
> > +static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> > +{
> > +     int ret = 0;
> > +     void __iomem *base;
> > +     struct device *dev = &adev->dev;
> > +     struct cti_drvdata *drvdata = NULL;
> > +     struct coresight_desc cti_desc;
> > +     struct coresight_platform_data *pdata = NULL;
> > +     struct resource *res = &adev->res;
> > +
> > +     /* driver data*/
> > +     drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> > +     if (!drvdata) {
> > +             ret = -ENOMEM;
> > +             dev_info(dev, "%s, mem err\n", __func__);
> > +             goto err_out;
> > +     }
> > +
> > +     /* Validity for the resource is already checked by the AMBA core */
> > +     base = devm_ioremap_resource(dev, res);
> > +     if (IS_ERR(base)) {
> > +             ret = PTR_ERR(base);
> > +             dev_info(dev, "%s, remap err\n", __func__);
> > +             goto err_out;
> > +     }
> > +     drvdata->base = base;
> > +
> > +     dev_set_drvdata(dev, drvdata);
> > +
> > +     /* default CTI device info  */
> > +     drvdata->ctidev.cpu = -1;
> > +     drvdata->ctidev.nr_trig_con = 0;
> > +     drvdata->ctidev.ctm_id = 0;
> > +     INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);
> > +
> > +     spin_lock_init(&drvdata->spinlock);
> > +
> > +     /* initialise CTI driver config values */
> > +     cti_set_default_config(dev, drvdata);
> > +
> > +     /* Parse the .dts for connections and signals */
> > +     pdata = coresight_cti_get_platform_data(dev);
>
> Here I would simply call cti_plat_get_hw_data() and not instantiate a *pdata.
> See below for more details.
>
> > +     if (IS_ERR(pdata)) {
> > +             dev_info(dev, "coresight_cti_get_platform_data err\n");
> > +             ret =  PTR_ERR(pdata);
> > +             goto err_out;
> > +     }
> > +
> > +     /* default to powered - could change on PM notifications */
> > +     drvdata->config.hw_powered = true;
> > +
> > +     /* set up device name - will depend if cpu bound or otherwise */
> > +     if (drvdata->ctidev.cpu >= 0)
> > +             cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d",
> > +                                            drvdata->ctidev.cpu);
> > +     else
> > +             cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev);
> > +     if (!cti_desc.name) {
> > +             ret = -ENOMEM;
> > +             goto err_out;
> > +     }
> > +
> > +     /* set up coresight component description */
> > +     cti_desc.pdata = pdata;
>
> Just set this to NULL and add a check in coresight_release_platform_data() that
> returns immediately if @pdata is NULL.  The latter should be done in a separate
> patch preceding this one.  If someone tries to do a cti_drvdata::csdev::pdata,
> we'll find out pretty quickly.
>
> With this:
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>

pdata is used later in the generic coresight_register function. We
need it to pass to this with 0 connection ports as we define
connections differently - but we need to allow the rest of the common
infrastructure to keep working for us.

Regards

Mike


> > +     cti_desc.type = CORESIGHT_DEV_TYPE_ECT;
> > +     cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI;
> > +     cti_desc.ops = &cti_ops;
> > +     cti_desc.groups = coresight_cti_groups;
> > +     cti_desc.dev = dev;
> > +     drvdata->csdev = coresight_register(&cti_desc);
> > +     if (IS_ERR(drvdata->csdev)) {
> > +             ret = PTR_ERR(drvdata->csdev);
> > +             goto err_out;
> > +     }
> > +
> > +     /* add to list of CTI devices */
> > +     mutex_lock(&ect_mutex);
> > +     list_add(&drvdata->node, &ect_net);
> > +     mutex_unlock(&ect_mutex);
> > +
> > +     /* set up release chain */
> > +     drvdata->csdev_release = drvdata->csdev->dev.release;
> > +     drvdata->csdev->dev.release = cti_device_release;
> > +
> > +     /* all done - dec pm refcount */
> > +     pm_runtime_put(&adev->dev);
> > +     dev_info(&drvdata->csdev->dev, "CTI initialized\n");
> > +     return 0;
> > +
> > +err_out:
> > +     return ret;
> > +}
> > +
> > +static struct amba_cs_uci_id uci_id_cti[] = {
> > +     {
> > +             /*  CTI UCI data */
> > +             .devarch        = 0x47701a14, /* CTI v2 */
> > +             .devarch_mask   = 0xfff0ffff,
> > +             .devtype        = 0x00000014, /* maj(0x4-debug) min(0x1-ECT) */
> > +     }
> > +};
> > +
> > +static const struct amba_id cti_ids[] = {
> > +     CS_AMBA_ID(0x000bb906), /* Coresight CTI (SoC 400), C-A72, C-A57 */
> > +     CS_AMBA_ID(0x000bb922), /* CTI - C-A8 */
> > +     CS_AMBA_ID(0x000bb9a8), /* CTI - C-A53 */
> > +     CS_AMBA_ID(0x000bb9aa), /* CTI - C-A73 */
> > +     CS_AMBA_UCI_ID(0x000bb9da, uci_id_cti), /* CTI - C-A35 */
> > +     CS_AMBA_UCI_ID(0x000bb9ed, uci_id_cti), /* Coresight CTI (SoC 600) */
> > +     { 0, 0},
> > +};
> > +
> > +static struct amba_driver cti_driver = {
> > +     .drv = {
> > +             .name   = "coresight-cti",
> > +             .owner = THIS_MODULE,
> > +             .suppress_bind_attrs = true,
> > +     },
> > +     .probe          = cti_probe,
> > +     .id_table       = cti_ids,
> > +};
> > +builtin_amba_driver(cti_driver);
> > diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
> > new file mode 100644
> > index 000000000000..e0d476533a82
> > --- /dev/null
> > +++ b/drivers/hwtracing/coresight/coresight-cti.h
> > @@ -0,0 +1,186 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2018 Linaro Limited, All rights reserved.
> > + * Author: Mike Leach <mike.leach@linaro.org>
> > + */
> > +
> > +#ifndef _CORESIGHT_CORESIGHT_CTI_H
> > +#define _CORESIGHT_CORESIGHT_CTI_H
> > +
> > +#include <asm/local.h>
> > +#include <linux/spinlock.h>
> > +#include "coresight-priv.h"
> > +
> > +/*
> > + * Device registers
> > + * 0x000 - 0x144: CTI programming and status
> > + * 0xEDC - 0xEF8: CTI integration test.
> > + * 0xF00 - 0xFFC: Coresight management registers.
> > + */
> > +/* CTI programming registers */
> > +#define CTICONTROL           0x000
> > +#define CTIINTACK            0x010
> > +#define CTIAPPSET            0x014
> > +#define CTIAPPCLEAR          0x018
> > +#define CTIAPPPULSE          0x01C
> > +#define CTIINEN(n)           (0x020 + (4 * n))
> > +#define CTIOUTEN(n)          (0x0A0 + (4 * n))
> > +#define CTITRIGINSTATUS              0x130
> > +#define CTITRIGOUTSTATUS     0x134
> > +#define CTICHINSTATUS                0x138
> > +#define CTICHOUTSTATUS               0x13C
> > +#define CTIGATE                      0x140
> > +#define ASICCTL                      0x144
> > +/* Integration test registers */
> > +#define ITCHINACK            0xEDC /* WO CTI CSSoc 400 only*/
> > +#define ITTRIGINACK          0xEE0 /* WO CTI CSSoc 400 only*/
> > +#define ITCHOUT                      0xEE4 /* WO RW-600 */
> > +#define ITTRIGOUT            0xEE8 /* WO RW-600 */
> > +#define ITCHOUTACK           0xEEC /* RO CTI CSSoc 400 only*/
> > +#define ITTRIGOUTACK         0xEF0 /* RO CTI CSSoc 400 only*/
> > +#define ITCHIN                       0xEF4 /* RO */
> > +#define ITTRIGIN             0xEF8 /* RO */
> > +/* management registers */
> > +#define CTIDEVAFF0           0xFA8
> > +#define CTIDEVAFF1           0xFAC
> > +
> > +/*
> > + * CTI CSSoc 600 has a max of 32 trigger signals per direction.
> > + * CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def.
> > + * Max of in and out defined in the DEVID register.
> > + * - pick up actual number used from .dts parameters if present.
> > + */
> > +#define CTIINOUTEN_MAX               32
> > +
> > +/**
> > + * Group of related trigger signals
> > + *
> > + * @nr_sigs: number of signals in the group.
> > + * @used_mask: bitmask representing the signal indexes in the group.
> > + * @sig_types: array of types for the signals, length nr_sigs.
> > + */
> > +struct cti_trig_grp {
> > +     int nr_sigs;
> > +     u32 used_mask;
> > +     int sig_types[0];
> > +};
> > +
> > +/**
> > + * Trigger connection - connection between a CTI and other (coresight) device
> > + * lists input and output trigger signals for the device
> > + *
> > + * @con_in: connected CTIIN signals for the device.
> > + * @con_out: connected CTIOUT signals for the device.
> > + * @con_dev: coresight device connected to the CTI, NULL if not CS device
> > + * @con_dev_name: name of connected device (CS or CPU)
> > + * @node: entry node in list of connections.
> > + */
> > +struct cti_trig_con {
> > +     struct cti_trig_grp *con_in;
> > +     struct cti_trig_grp *con_out;
> > +     struct coresight_device *con_dev;
> > +     char *con_dev_name;
> > +     struct list_head node;
> > +};
> > +
> > +/**
> > + * struct cti_device - description of CTI device properties.
> > + *
> > + * @nt_trig_con: Number of external devices connected to this device.
> > + * @ctm_id: which CTM this device is connected to (by default it is
> > + *          assumed there is a single CTM per SoC, ID 0).
> > + * @trig_cons: list of connections to this device.
> > + * @cpu: CPU ID if associated with CPU, -1 otherwise.
> > + */
> > +struct cti_device {
> > +     int nr_trig_con;
> > +     u32 ctm_id;
> > +     struct list_head trig_cons;
> > +     int cpu;
> > +};
> > +
> > +/**
> > + * struct cti_config - configuration of the CTI device hardware
> > + *
> > + * @nr_trig_max: Max number of trigger signals implemented on device.
> > + *            (max of trig_in or trig_out) - from ID register.
> > + * @nr_ctm_channels: number of available CTM channels - from ID register.
> > + * @enable_req_count: CTI is enabled alongside >=1 associated devices.
> > + * @hw_enabled: true if hw is currently enabled.
> > + * @hw_powered: true if associated cpu powered on, or no cpu.
> > + * @trig_in_use: bitfield of in triggers registered as in use.
> > + * @trig_out_use: bitfield of out triggers registered as in use.
> > + * @trig_out_filter: bitfield of out triggers that are blocked if filter
> > + *                enabled. Typically this would be dbgreq / restart on
> > + *                a core CTI.
> > + * @trig_filter_enable: 1 if filtering enabled.
> > + * @xtrig_rchan_sel: channel selection for xtrigger connection show.
> > + * @ctiappset: CTI Software application channel set.
> > + * @ctiinout_sel: register selector for INEN and OUTEN regs.
> > + * @ctiinen: enable input trigger to a channel.
> > + * @ctiouten: enable output trigger from a channel.
> > + * @ctigate: gate channel output from CTI to CTM.
> > + * @asicctl: asic control register.
> > + */
> > +struct cti_config {
> > +     /* hardware description */
> > +     int nr_ctm_channels;
> > +     int nr_trig_max;
> > +
> > +     /* cti enable control */
> > +     atomic_t enable_req_count;
> > +     bool hw_enabled;
> > +     bool hw_powered;
> > +
> > +     /* registered triggers and filtering */
> > +     u32 trig_in_use;
> > +     u32 trig_out_use;
> > +     u32 trig_out_filter;
> > +     bool trig_filter_enable;
> > +     u8 xtrig_rchan_sel;
> > +
> > +     /* cti cross trig programmable regs */
> > +     u32 ctiappset;
> > +     u8 ctiinout_sel;
> > +     u32 ctiinen[CTIINOUTEN_MAX];
> > +     u32 ctiouten[CTIINOUTEN_MAX];
> > +     u32 ctigate;
> > +     u32 asicctl;
> > +};
> > +
> > +/**
> > + * struct cti_drvdata - specifics for the CTI device
> > + * @base:    Memory mapped base address for this component..
> > + * @csdev:   Standard CoreSight device information.
> > + * @ctidev:  Extra information needed by the CTI/CTM framework.
> > + * @spinlock:        Control data access to one at a time.
> > + * @config:  Configuration data for this CTI device.
> > + * @node:    List entry of this device in the list of CTI devices.
> > + * @csdev_release: release function for underlying coresight_device.
> > + */
> > +struct cti_drvdata {
> > +     void __iomem *base;
> > +     struct coresight_device *csdev;
> > +     struct cti_device ctidev;
> > +     spinlock_t spinlock;
> > +     struct cti_config config;
> > +     struct list_head node;
> > +     void (*csdev_release)(struct device *dev);
> > +};
> > +
> > +/* private cti driver fns & vars */
> > +extern const struct attribute_group *coresight_cti_groups[];
> > +int cti_add_default_connection(struct device *dev,
> > +                            struct cti_drvdata *drvdata);
> > +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
> > +                          struct cti_trig_con *tc,
> > +                          struct coresight_device *csdev,
> > +                          const char *assoc_dev_name);
> > +struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
> > +                                        int out_sigs);
> > +int cti_enable(struct coresight_device *csdev);
> > +int cti_disable(struct coresight_device *csdev);
> > +struct coresight_platform_data *
> > +coresight_cti_get_platform_data(struct device *dev);
> > +
> > +#endif  /* _CORESIGHT_CORESIGHT_CTI_H */
> > diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
> > index ef20f74c85fa..1a5fdf2710ff 100644
> > --- a/drivers/hwtracing/coresight/coresight.c
> > +++ b/drivers/hwtracing/coresight/coresight.c
> > @@ -955,6 +955,9 @@ static struct device_type coresight_dev_type[] = {
> >       {
> >               .name = "helper",
> >       },
> > +     {
> > +             .name = "ect",
> > +     },
> >  };
> >
> >  static void coresight_device_release(struct device *dev)
> > diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> > index 44e552de419c..b3e582d96a34 100644
> > --- a/include/linux/coresight.h
> > +++ b/include/linux/coresight.h
> > @@ -41,6 +41,7 @@ enum coresight_dev_type {
> >       CORESIGHT_DEV_TYPE_LINKSINK,
> >       CORESIGHT_DEV_TYPE_SOURCE,
> >       CORESIGHT_DEV_TYPE_HELPER,
> > +     CORESIGHT_DEV_TYPE_ECT,
> >  };
> >
> >  enum coresight_dev_subtype_sink {
> > @@ -68,6 +69,12 @@ enum coresight_dev_subtype_helper {
> >       CORESIGHT_DEV_SUBTYPE_HELPER_CATU,
> >  };
> >
> > +/* Embedded Cross Trigger (ECT) sub-types */
> > +enum coresight_dev_subtype_ect {
> > +     CORESIGHT_DEV_SUBTYPE_ECT_NONE,
> > +     CORESIGHT_DEV_SUBTYPE_ECT_CTI,
> > +};
> > +
> >  /**
> >   * union coresight_dev_subtype - further characterisation of a type
> >   * @sink_subtype:    type of sink this component is, as defined
> > @@ -78,6 +85,8 @@ enum coresight_dev_subtype_helper {
> >   *                   by @coresight_dev_subtype_source.
> >   * @helper_subtype:  type of helper this component is, as defined
> >   *                   by @coresight_dev_subtype_helper.
> > + * @ect_subtype:        type of cross trigger this component is, as
> > + *                   defined by @coresight_dev_subtype_ect
> >   */
> >  union coresight_dev_subtype {
> >       /* We have some devices which acts as LINK and SINK */
> > @@ -87,6 +96,7 @@ union coresight_dev_subtype {
> >       };
> >       enum coresight_dev_subtype_source source_subtype;
> >       enum coresight_dev_subtype_helper helper_subtype;
> > +     enum coresight_dev_subtype_ect ect_subtype;
> >  };
> >
> >  /**
> > @@ -196,6 +206,7 @@ static struct coresight_dev_list (var) = {                                \
> >  #define sink_ops(csdev)              csdev->ops->sink_ops
> >  #define link_ops(csdev)              csdev->ops->link_ops
> >  #define helper_ops(csdev)    csdev->ops->helper_ops
> > +#define ect_ops(csdev)               csdev->ops->ect_ops
> >
> >  /**
> >   * struct coresight_ops_sink - basic operations for a sink
> > @@ -262,11 +273,23 @@ struct coresight_ops_helper {
> >       int (*disable)(struct coresight_device *csdev, void *data);
> >  };
> >
> > +/**
> > + * struct coresight_ops_ect - Ops for an embedded cross trigger device
> > + *
> > + * @enable   : Enable the device
> > + * @disable  : Disable the device
> > + */
> > +struct coresight_ops_ect {
> > +     int (*enable)(struct coresight_device *csdev);
> > +     int (*disable)(struct coresight_device *csdev);
> > +};
> > +
> >  struct coresight_ops {
> >       const struct coresight_ops_sink *sink_ops;
> >       const struct coresight_ops_link *link_ops;
> >       const struct coresight_ops_source *source_ops;
> >       const struct coresight_ops_helper *helper_ops;
> > +     const struct coresight_ops_ect *ect_ops;
> >  };
> >
> >  #ifdef CONFIG_CORESIGHT
> > --
> > 2.17.1
> >



-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 01/14] coresight: cti: Initial CoreSight CTI Driver
  2019-11-25 19:03   ` Suzuki Kuruppassery Poulose
@ 2019-11-29 12:06     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-29 12:06 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi Suzuki,

Will be re-spinning due to later patches - so will fixup as requested

Thanks

Mike

On Mon, 25 Nov 2019 at 19:03, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:18, Mike Leach wrote:
> > This introduces a baseline CTI driver and associated configuration files.
> >
> > Uses the platform agnostic naming standard for CoreSight devices, along
> > with a generic platform probing method that currently supports device
> > tree descriptions, but allows for the ACPI bindings to be added once these
> > have been defined for the CTI devices.
> >
> > Driver will probe for the device on the AMBA bus, and load the CTI driver
> > on CoreSight ID match to CTI IDs in tables.
> >
> > Initial sysfs support for enable / disable provided.
> >
> > Default CTI interconnection data is generated based on hardware
> > register signal counts, with no additional connection information.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
>
> Looks good to me.  Some very minor nits, feel free to ignore if you are
> not respinning the series.
>
> > +/*
> > + * Look at the HW DEVID register for some of the HW settings.
> > + * DEVID[15:8] - max number of in / out triggers.
> > + */
> > +#define CTI_DEVID_MAXTRIGS(devid_val) (int)((devid_val & 0xFF00) >> 8)
>
> BMVAL(devid_val, 15, 8)
>
> > +
> > +/* DEVID[19:16] - number of CTM channels */
> > +#define CTI_DEVID_CTMCHANNELS(devid_val) (int)((devid_val & 0xF0000) >> 16)
>
> BMVAL(devid_val, 19, 16)
>
> > +
> > +static void cti_set_default_config(struct device *dev,
> > +                                struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_config *config = &drvdata->config;
> > +     u32 devid;
> > +
> > +     devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
> > +     config->nr_trig_max = CTI_DEVID_MAXTRIGS(devid);
> > +
> > +     /*
> > +      * no current hardware should exceed this, but protect the driver
> > +      * in case of fault / out of spec hw
> > +      */
> > +     if (config->nr_trig_max > CTIINOUTEN_MAX) {
> > +             dev_warn_once(dev,
> > +                     "Limiting HW MaxTrig value(%d) to driver max(%d)\n",
> > +                     config->nr_trig_max, CTIINOUTEN_MAX);
> > +             config->nr_trig_max = CTIINOUTEN_MAX;
> > +     }
> > +
> > +     config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid);
> > +
> > +     /* Most regs default to 0 as zalloc'ed except...*/
> > +     config->trig_filter_enable = true;
> > +     config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
> > +     atomic_set(&config->enable_req_count, 0);
> > +}
> > +
> > +/*
> > + * Add a connection entry to the list of connections for this
> > + * CTI device.
> > + */
> > +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
> > +                          struct cti_trig_con *tc,
> > +                          struct coresight_device *csdev,
> > +                          const char *assoc_dev_name)
> > +{
> > +     struct cti_device *cti_dev = &drvdata->ctidev;
> > +
> > +     tc->con_dev = csdev;
> > +     /*
> > +      * Prefer actual associated CS device dev name to supplied value -
> > +      * which is likely to be node name / other conn name.
> > +      */
> > +     if (csdev)
> > +             tc->con_dev_name = devm_kstrdup(dev,
> > +                                             dev_name(&csdev->dev),
> > +                                             GFP_KERNEL);
> > +     else if (assoc_dev_name != NULL)
> > +             tc->con_dev_name = devm_kstrdup(dev,
> > +                                             assoc_dev_name, GFP_KERNEL);
> > +     list_add_tail(&tc->node, &cti_dev->trig_cons);
> > +     cti_dev->nr_trig_con++;
> > +
> > +     /* add connection usage bit info to overall info */
> > +     drvdata->config.trig_in_use |= tc->con_in->used_mask;
> > +     drvdata->config.trig_out_use |= tc->con_out->used_mask;
>
> Do we need to make sure that they are exclusive ?
>
>   WARN_ON(drvdata->config.trig_in_use ^ ~(tc->con_in->used_mask));
>   WARN_ON(drvdata->config.trig_out_use ^ ~(tc->con_out->used_mask));
>
> > +/** cti ect operations **/
> > +int cti_enable(struct coresight_device *csdev)
> > +{
> > +     struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> > +
> > +     /* enable hardware with refcount */
>
> nit: left over comment from previous revision ?
>
> > +     return cti_enable_hw(drvdata);
> > +}
> > +
> > +int cti_disable(struct coresight_device *csdev)
> > +{
> > +     struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> > +
> > +     /* disable hardware with refcount */
>
> same here ?
>
> > +     return cti_disable_hw(drvdata);
> > +}
> > +
>
> > +
> > +static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> > +{
> > +     int ret = 0;
> > +     void __iomem *base;
> > +     struct device *dev = &adev->dev;
> > +     struct cti_drvdata *drvdata = NULL;
> > +     struct coresight_desc cti_desc;
> > +     struct coresight_platform_data *pdata = NULL;
> > +     struct resource *res = &adev->res;
> > +
> > +     /* driver data*/
> > +     drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> > +     if (!drvdata) {
> > +             ret = -ENOMEM;
> > +             dev_info(dev, "%s, mem err\n", __func__);
>
> dev_err() ? As they may have higher priority than "info" and will get
> displayed in the rare chance of them getting hit.
>
> > +             goto err_out;
> > +     }
> > +
> > +     /* Validity for the resource is already checked by the AMBA core */
> > +     base = devm_ioremap_resource(dev, res);
> > +     if (IS_ERR(base)) {
> > +             ret = PTR_ERR(base);
> > +             dev_info(dev, "%s, remap err\n", __func__);
>
> same here, dev_err()
>
> > +             goto err_out;
> > +     }
> > +     drvdata->base = base;
> > +
> > +     dev_set_drvdata(dev, drvdata);
> > +
> > +     /* default CTI device info  */
> > +     drvdata->ctidev.cpu = -1;
> > +     drvdata->ctidev.nr_trig_con = 0;
> > +     drvdata->ctidev.ctm_id = 0;
> > +     INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);
> > +
> > +     spin_lock_init(&drvdata->spinlock);
> > +
> > +     /* initialise CTI driver config values */
> > +     cti_set_default_config(dev, drvdata);
> > +
> > +     /* Parse the .dts for connections and signals */
>
> minor nit: I would not mention about ".dts" here. The function name is
> implicit. You could actually remove that comment.
>
> As mentioned above, the comments are minor nits. So you may add
> with/without addressing them:
>
> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>


-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs
  2019-11-27 18:26   ` Suzuki Kuruppassery Poulose
@ 2019-11-29 12:47     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-29 12:47 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi Suzuki,


On Wed, 27 Nov 2019 at 18:26, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > Adds in sysfs programming support for the CTI function register sets.
> > Allows direct manipulation of channel / trigger association registers.
> >
> > Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >   .../hwtracing/coresight/coresight-cti-sysfs.c | 362 ++++++++++++++++++
> >   drivers/hwtracing/coresight/coresight-cti.c   |  19 +
> >   drivers/hwtracing/coresight/coresight-cti.h   |   5 +
> >   3 files changed, 386 insertions(+)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > index 507f8eb487fe..02d3ee0c1278 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > @@ -109,6 +109,362 @@ static struct attribute *coresight_cti_mgmt_attrs[] = {
> >       NULL,
> >   };
> >
> > +/* CTI low level programming registers */
> > +
> > +/*
> > + * Show a simple 32 bit value if enabled and powered.
> > + * If inaccessible & pcached_val not NULL then show cached value.
> > + */
>
> Also I am not sure if it makes sense to mention that the value is cached.
>
> > +static ssize_t cti_reg32_show(struct device *dev, char *buf,
> > +                           u32 *pcached_val, int reg_offset)
> > +{
> > +     u32 val = 0;
>    +    char *state = "";
>
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +     struct cti_config *config = &drvdata->config;
> > +
> > +     spin_lock(&drvdata->spinlock);
> > +     if ((reg_offset >= 0) && CTI_PWR_ENA(config)) {
>
> minor nit: Personally I don't like the naming here. This could simply
> be: cti_accessible(config) , may be defined as a static inline function
> instead of a macro:
>
> static inline bool cti_accessible(struct cti_drvdata *drvdata)
> {
>         struct cti_config *cfg = &drvdata->config;
>
>         return cfg->hw_powered && cfg->hw_enabled;
> }
>
>

Since this is a generic access function used throughout the file - the
cached pointer is an indicator used by the callee that there is a
value available if the CTI is unpowered  / disabled - so the function
can show an appropriate value which will be taken from the config
structure.

So I don't think it is relevant to show that a "cached" value is being
used to show the user. If you look at similar functions in the ETM
drivers for example, quite often a show function simple shows that
stored value from a config structure without ever looking at the
register in the device.

As to naming - the name is chosen to represent a specific state - both
powered and enabled. The sysfs interface is accessible in any state  -
powered / unpowered  , enabled /disabled - so I am being specific.
Unlike the ETM, this hardware can have registers programmed while
enabled - and for some such as apppulse this is the only time it makes
sense to use them.

I don't mind either way between macro / inline function - though it
still has to be declared in the header as it is used in multiple .c
files.
I'd be inclined to call it cti_active() if preferred to cti_pwr_ena -
active implies that the CTI is in operation.

Thanks

Mike


> > +             CS_UNLOCK(drvdata->base);
> > +             val = readl_relaxed(drvdata->base + reg_offset);
> > +             if (pcached_val)
> > +                     *pcached_val = val;
> > +             CS_LOCK(drvdata->base);
> > +     } else if (pcached_val) {
> > +             val = *pcached_val;
>
>    +            state = " (cached)";
> > +     }
> > +     spin_unlock(&drvdata->spinlock);
> > +     return scnprintf(buf, PAGE_SIZE, "%#x\n", val);
>    +    return scnprintf(buf, PAGE_SIZE, "%#x%s\n", val, state);
>
> > +}
> > +
> > +/*
> > + * Store a simple 32 bit value.
> > + * If pcached_val not NULL, then copy to here too,
> > + * if reg_offset >= 0 then write through if enabled.
> > + */
> > +static ssize_t cti_reg32_store(struct device *dev, const char *buf,
> > +                            size_t size, u32 *pcached_val, int reg_offset)
>
>
> > +static ssize_t appclear_store(struct device *dev,
> > +                           struct device_attribute *attr,
> > +                           const char *buf, size_t size)
> > +{
> > +     unsigned long val;
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +     struct cti_config *config = &drvdata->config;
> > +
> > +     if (kstrtoul(buf, 0, &val))
> > +             return -EINVAL;
> > +
> > +     spin_lock(&drvdata->spinlock);
> > +
> > +     /* a 1'b1 in appclr clears down the same bit in appset*/
>
> nit: a 0b1 ?
>
Syntax is <bitwidth>'<radix><value> - a habit picked up from verilog.

> > +     config->ctiappset &= ~val;
> > +
> > +     /* write through if enabled */
> > +     if (CTI_PWR_ENA(config))
> > +             cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
> > +     spin_unlock(&drvdata->spinlock);
> > +     return size;
> > +}
> > +static DEVICE_ATTR_WO(appclear);
> > +
>
> Otherwise looks good to me.
>
> Suzuki



-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs
  2019-11-28 10:54   ` Suzuki Kuruppassery Poulose
  2019-11-28 17:20     ` Mathieu Poirier
@ 2019-11-29 12:50     ` Mike Leach
  1 sibling, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-29 12:50 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi Suzuki, Mathieu,

On Thu, 28 Nov 2019 at 10:54, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > Adds in sysfs programming support for the CTI function register sets.
> > Allows direct manipulation of channel / trigger association registers.
> >
> > Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
>
>
> > +/*
> > + * #define CTI_DEBUG_INTEGRATION_CTRL to enable the access to the integration
> > + * control registers. Normally only used to investigate connection data.
> > + */
>
> On a second thought, I have some comments on this symbol.
>
> Given that the integration control registers may be useful for people to
> find the device connections, I strongly feel that this is provided
> via a CONFIG symbol rather than a  debug symbol within the code.
>
> i.e, CONFIG_CTI_DEBUG_INTEGRATION_CTRL, to help the people better.
> Codewise this doesn't make much difference, but it certainly makes
> it more easier for people to use it.
>
> We have used debug symbols elsewhere in the drivers for pure functional
> debugging purposes. However I feel this is case is superior.
>
>
> Cheers
> Suzuki

Per the comment above, and the discussions following, I would agree
that using a config symbol makes it easier for users to select the
feature and gives us an opportunity to put in some explanation as to
what it does.

Thanks

Mike

-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 04/14] coresight: cti: Add sysfs trigger / channel programming API
  2019-11-27 18:40   ` Suzuki Kuruppassery Poulose
@ 2019-11-29 13:01     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-29 13:01 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi Suzuki,


On Wed, 27 Nov 2019 at 18:40, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > Adds a user API to allow programming of CTI by trigger ID and
> > channel number. This will take the channel and trigger ID supplied
> > by the user and program the appropriate register values.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
>
> > +
> > +static ssize_t chan_xtrigs_view_show(struct device *dev,
> > +                                  struct device_attribute *attr,
> > +                                  char *buf)
> > +{
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +     struct cti_config *cfg = &drvdata->config;
> > +     int used = 0, reg_idx;
> > +     int buf_sz = PAGE_SIZE;
> > +     u32 chan_mask = BIT(cfg->xtrig_rchan_sel);
> > +
> > +     used += scnprintf(buf, buf_sz, "[%d] IN: ", cfg->xtrig_rchan_sel);
> > +     for (reg_idx = 0;
> > +          reg_idx < drvdata->config.nr_trig_max;
> > +          reg_idx++) {
> > +             if (chan_mask & cfg->ctiinen[reg_idx]) {
> > +                     used += scnprintf(buf + used, buf_sz - used, "%d ",
> > +                                       reg_idx);
> > +             }
> > +     }
>
> As a security measure, we must make sure that we have space left in the
> buffer. We could end up passing "negative" numbers for the size
> argument, in the worst case.
>

The return value from scnprintf() is always the _actual_ number of
characters added to the buffer, not as per snprintf() which returns
the number that could have been printed if there were sufficient
space.
Thus used can never exceed the buffer size.

Regards

Mike


> > +
> > +     used += scnprintf(buf + used, buf_sz - used, "OUT: ");
> > +     for (reg_idx = 0;
> > +          reg_idx < drvdata->config.nr_trig_max;
> > +          reg_idx++) {
> > +             if (chan_mask & cfg->ctiouten[reg_idx]) {
> > +                     used += scnprintf(buf + used, buf_sz - used, "%d ",
> > +                                       reg_idx);
> > +             }
> > +     }
> > +     used += scnprintf(buf + used, buf_sz - used, "\n");
> > +     return used;
> > +}
> > +static DEVICE_ATTR_RW(chan_xtrigs_view);
>
>
> The rest looks fine to me.
>
> Suzuki



-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions.
  2019-11-22 23:33   ` Rob Herring
@ 2019-11-29 13:50     ` Mike Leach
  2019-11-29 14:12       ` Suzuki Kuruppassery Poulose
  0 siblings, 1 reply; 62+ messages in thread
From: Mike Leach @ 2019-11-29 13:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier, Suzuki K. Poulose

Hi Rob,

On Fri, 22 Nov 2019 at 23:33, Rob Herring <robh@kernel.org> wrote:
>
> On Tue, Nov 19, 2019 at 11:19:03PM +0000, Mike Leach wrote:
> > Adds new coresight-cti.yaml file describing the bindings required to define
> > CTI in the device trees.
> >
> > Adds an include file to dt-bindings/arm to define constants describing
> > common signal functionality used in CoreSight and generic usage.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >  .../bindings/arm/coresight-cti.yaml           | 303 ++++++++++++++++++
> >  .../devicetree/bindings/arm/coresight.txt     |   7 +
> >  MAINTAINERS                                   |   2 +
> >  include/dt-bindings/arm/coresight-cti-dt.h    |  37 +++
> >  4 files changed, 349 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/arm/coresight-cti.yaml
> >  create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h
> >
> > diff --git a/Documentation/devicetree/bindings/arm/coresight-cti.yaml b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> > new file mode 100644
> > index 000000000000..882c72f1c798
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> > @@ -0,0 +1,303 @@
> > +# SPDX-License-Identifier: GPL-2.0
>
> Dual license new bindings please:
>
> (GPL-2.0-only OR BSD-2-Clause)
>
OK.

> > +# Copyright 2019 Linaro Ltd.
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/arm/coresight-cti.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: ARM Coresight Cross Trigger Interface (CTI) device.
> > +
> > +description: |
> > +  The CoreSight Embedded Cross Trigger (ECT) consists of CTI devices connected
> > +  to one or more CoreSight components and/or a CPU, with CTIs interconnected in
> > +  a star topology via the CTM (which is not programmable). The ECT components
> > +  are not part of the trace generation data path and are thus not part of the
> > +  CoreSight graph described in the general CoreSight bindings file
> > +  coresight.txt.
> > +
> > +  The CTI component properties define the connections between the individual
> > +  CTI and the components it is directly connected to, consisting of input and
> > +  output hardware trigger signals. CTIs can have a maximum number of input and
> > +  output hardware trigger signals (8 each for v1 CTI, 32 each for v2 CTI). The
> > +  number is defined at design time, the maximum of each defined in the DEVID
> > +  register.
> > +
> > +  CTIs are interconnected in a star topology via the CTM, using a number of
> > +  programmable channels usually 4, but again implementation defined and
> > +  described in the DEVID register. The star topology is not required to be
> > +  described in the bindings as the actual connections are software
> > +  programmable.
> > +
> > +  In general the connections between CTI and components via the trigger signals
> > +  are implementation defined, other than when v8 core and ETM is present.
> > +  The v8 architecture defines the required signal connections between CPU core
> > +  and CTI, and ETM and CTI, if the ETM if present.
> > +
> > +  When only minimal information is available for the CTI trigger connections,
> > +  then a minimal driver binding can be declare with no explicit trigger
> > +  signals. This will result in the using the DEVID register to set the
> > +  input and output triggers and channels in use. Any user / client
> > +  application will require additional information on the connections
> > +  between the CTI and other components for correct operation. This minimal
> > +  binding may be used when using the Integration Control registers to
> > +  discover connections between CTI and other CoreSight components,
> > +
> > +  Certain triggers between CoreSight devices and the CTI have specific types
> > +  and usages. These can be defined along with the signal indexes with the
> > +  constants defined in <dt-bindings/arm/coresight-cti-dt.h>
> > +
> > +  For example a CTI connected to a core will usually have a DBGREQ signal. This
> > +  is defined in the binding as type PE_EDBGREQ. These types will appear in an
> > +  optional array alongside the signal indexes. Omitting types will default all
> > +  signals to GEN_IO.
> > +
> > +  Note that some hardware trigger signals can be connected to non-CoreSight
> > +  components (e.g. UART etc) depending on hardware implementation.
> > +
> > +maintainers:
> > +  - Mike Leach <mike.leach@linaro.org>
> > +
> > +allOf:
> > +  - $ref: /schemas/arm/primecell.yaml#
> > +
> > +# Need a custom select here or 'arm,primecell' will match on lots of nodes
> > +select:
> > +  properties:
> > +    compatible:
> > +      contains:
> > +        enum:
> > +          - arm,coresight-cti
> > +  required:
> > +    - compatible
> > +
> > +properties:
> > +  $nodename:
> > +    pattern: "^cti(@[0-9a-f,]+)*$"
>
> Unit address should not be optional nor have a comma.
>

Will fix.

> > +  compatible:
> > +    items:
> > +      - const: arm,coresight-cti
> > +      - const: arm,primecell
> > +
> > +  reg:
> > +    items:
> > +      - description: device programming registers
>
> Just "maxItems: 1" is sufficient.
>

OK

> > +
> > +  arm,cti-v8-arch:
> > +    type: boolean
> > +    description:
> > +      This CTI follows the v8 architecturally mandated layout for a CTI.
>
> Seems like the compatible or primecell ID registers should be used for
> something like this.
>

Unfortunately it is possible and has happened that the same primecell
regs for a CTI connected to a v8 core and one that is used as a
general system CTI appear in the same system.
There is no architectural requirement on the CTI to indicate that its
external connections are as per v8 architecture spec when connected to
 a PE/ETM combo.

Therefore a compatible "arm,coresight-cti-v8" would seem the best
route. I'll update the compatible portion of the schema and handling
code accordingly.

> > +      Bindings declaring this must declare a cpu, and optionally a single
> > +      arm,cs-dev-assoc may be present to define an attached ETM. No additional
> > +      trig-conns nodes are permitted. The driver will build a connection model
> > +      according to architectural requirements. This will include a filter on
> > +      the CPU dbgreq signal as described above.
> > +
> > +  cpu:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: Handle to cpu this device is associated with.
> > +
> > +  arm,cti-ctm-id:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/uint32
> > +    description:
> > +      Defines the CTM this CTI is connected to, in large systems with multiple
> > +      separate CTI/CTM nets. Typically multi-socket systems where the CTM is
> > +      propagated between sockets.
> > +
> > +  arm,cs-dev-assoc:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/phandle
> > +    description:
> > +      defines a phandle reference to an associated CoreSight trace device.
>
> s/defines/Defines/
>
OK

> > +      When the associated trace device is enabled, then the respective CTI
> > +      will be enabled. Use in a trig-conns node, or in CTI base node when
> > +      arm,cti-v8-arch present. If the associated device has not been registered
> > +      then the node name will be stored as the connection name for later
> > +      resolution. If the associated device is not a CoreSight device or not
> > +      registered then the node name will remain the connection name and
> > +      automatic enabling will not occur.
> > +
> > +patternProperties:
> > +  '^trig_conns@[0-9]+$':
>
> trig-conns@...
>
will fix.

> > +    type: object
> > +    description:
> > +      A trigger connections child node which describes the trigger signals
> > +      between this CTI and another hardware device. This device may be a CPU,
> > +      CoreSight device, any other hardware device or simple external IO lines.
> > +      The connection may have both input and output triggers, or only one or the
> > +      other.
> > +
> > +    properties:
> > +
> > +      arm,trig-in-sigs:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of CTI trigger in signal numbers in use by a trig-conns node.
> > +
> > +      arm,trig-in-types:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of constants representing the types for the CTI trigger in
> > +          signals. Types in this array match to the corresponding signal in the
> > +          arm,trig-in-sigs array. If the -types array is smaller, or omitted
> > +          completely, then the types will default to GEN_IO.
> > +
> > +      arm,trig-out-sigs:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of CTI trigger out signal numbers in use by a trig-conns node.
> > +
> > +      arm,trig-out-types:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of constants representing the types for the CTI trigger out
> > +          signals. Types in this array match to the corresponding signal
> > +          in the arm,trig-out-sigs array. If the "-types" array is smaller,
> > +          or omitted completely, then the types will default to GEN_IO.
> > +
> > +      arm,trig-filters:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of CTI trigger out signals that will be blocked from becoming
> > +          active, unless filtering is disabled on the driver.
> > +
> > +      arm,trig-conn-name:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/string
> > +        description:
> > +          Defines a connection name that will be displayed, if the cpu or
> > +          arm,cs-dev-assoc properties are not being used in this connection.
> > +          Principle use for CTI that are connected to non-CoreSight devices, or
> > +          external IO.
> > +
> > +    anyOf:
> > +      - required:
> > +        - arm,trig-in-sigs
> > +      - required:
> > +        - arm,trig-out-sigs
> > +    oneOf:
> > +      - required:
> > +        - arm,trig-conn-name
> > +      - required:
> > +        - cpu
> > +      - required:
> > +        - arm,cs-dev-assoc
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
> > +
> > +examples:
> > +  # minimum CTI definition. DEVID register used to set number of triggers.
> > +  - |
> > +    cti@20020000 {
> > +      compatible = "arm,coresight-cti", "arm,primecell";
> > +      reg = <0x20020000 0x1000>;
> > +
> > +      clocks = <&soc_smc50mhz>;
> > +      clock-names = "apb_pclk";
> > +    };
> > +  #  v8 architecturally defined CTI - CPU + ETM connections generated by the
> > +  #  driver according to the v8 architecture specification.
> > +  - |
> > +    cti@859000 {
> > +      compatible = "arm,coresight-cti", "arm,primecell";
> > +      reg = <0x859000 0x1000>;
> > +
> > +      clocks = <&soc_smc50mhz>;
> > +      clock-names = "apb_pclk";
> > +
> > +      arm,cti-v8-arch;
> > +      cpu = <&CPU1>;
> > +      arm,cs-dev-assoc = <&etm1>;
> > +    };
> > +  # Implementation defined CTI - CPU + ETM connections explicitly defined..
> > +  # Shows use of type constants from dt-bindings/arm/coresight-cti-dt.h
> > +  - |
> > +    #include <dt-bindings/arm/coresight-cti-dt.h>
> > +
> > +    cti@858000 {
> > +      compatible = "arm,coresight-cti", "arm,primecell";
> > +      reg = <0x858000 0x1000>;
> > +
> > +      clocks = <&soc_smc50mhz>;
> > +      clock-names = "apb_pclk";
> > +
> > +      arm,cti-ctm-id = <1>;
> > +
> > +      trig-conns@0 {
> > +            arm,trig-in-sigs = <4 5 6 7>;
> > +            arm,trig-in-types = <ETM_EXTOUT
> > +                                 ETM_EXTOUT
> > +                                 ETM_EXTOUT
> > +                                 ETM_EXTOUT>;
> > +            arm,trig-out-sigs = <4 5 6 7>;
> > +            arm,trig-out-types = <ETM_EXTIN
> > +                                  ETM_EXTIN
> > +                                  ETM_EXTIN
> > +                                  ETM_EXTIN>;
> > +            arm,cs-dev-assoc = <&etm0>;
> > +      };
> > +
> > +      trig-conns@1 {
> > +            cpu = <&CPU0>;
> > +            arm,trig-in-sigs = <0 1>;
> > +            arm,trig-in-types = <PE_DBGTRIGGER
> > +                                 PE_PMUIRQ>;
> > +            arm,trig-out-sigs=<0 1 2 >;
> > +            arm,trig-out-types = <PE_EDBGREQ
> > +                                  PE_DBGRESTART
> > +                                  PE_CTIIRQ>;
> > +
> > +            arm,trig-filters = <0>;
> > +      };
> > +    };
> > +  # Implementation defined CTI - none CoreSight component connections.
> > +  - |
> > +    cti@20110000 {
> > +      compatible = "arm,coresight-cti", "arm,primecell";
> > +      reg = <0 0x20110000 0 0x1000>;
> > +
> > +      clocks = <&soc_smc50mhz>;
> > +      clock-names = "apb_pclk";
> > +
> > +      trig-conns@0 {
> > +        arm,trig-in-sigs=<0>;
> > +        arm,trig-in-types=<GEN_INTREQ>;
> > +        arm,trig-out-sigs=<0>;
> > +        arm,trig-out-types=<GEN_HALTREQ>;
> > +        arm,trig-conn-name = "sys_profiler";
> > +      };
> > +
> > +      trig-conns@1 {
> > +        arm,trig-out-sigs=<2 3>;
> > +        arm,trig-out-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> > +        arm,trig-conn-name = "watchdog";
> > +      };
> > +
> > +      trig-conns@2 {
> > +        arm,trig-in-sigs=<1 6>;
> > +        arm,trig-in-types=<GEN_HALTREQ GEN_RESTARTREQ>;
> > +        arm,trig-conn-name = "g_counter";
> > +      };
> > +    };
> > +
> > +...
> > \ No newline at end of file
>
> '...' is preferred, but the fix the lack of newline.
>
Will do.

Thanks for the feedback.

Mike

> > diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
> > index d02c42d21f2f..846f6daae71b 100644
> > --- a/Documentation/devicetree/bindings/arm/coresight.txt
> > +++ b/Documentation/devicetree/bindings/arm/coresight.txt
> > @@ -45,6 +45,10 @@ its hardware characteristcs.
> >               - Coresight Address Translation Unit (CATU)
> >                       "arm,coresight-catu", "arm,primecell";
> >
> > +             - Coresight Cross Trigger Interface (CTI):
> > +                     "arm,coresight-cti", "arm,primecell";
> > +                     See coresight-cti.yaml for full CTI definitions.
> > +
> >       * reg: physical base address and length of the register
> >         set(s) of the component.
> >
> > @@ -72,6 +76,9 @@ its hardware characteristcs.
> >       * reg-names: the only acceptable values are "stm-base" and
> >         "stm-stimulus-base", each corresponding to the areas defined in "reg".
> >
> > +* Required properties for Coresight Cross Trigger Interface (CTI)
> > +     See coresight-cti.yaml for full CTI definitions.
> > +
> >  * Required properties for devices that don't show up on the AMBA bus, such as
> >    non-configurable replicators and non-configurable funnels:
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 9de89d75dbcc..8d01a74068f7 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -1608,9 +1608,11 @@ R:     Suzuki K Poulose <suzuki.poulose@arm.com>
> >  L:   linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
> >  S:   Maintained
> >  F:   drivers/hwtracing/coresight/*
> > +F:   include/dt-bindings/arm/coresight-cti-dt.h
> >  F:   Documentation/trace/coresight/*
> >  F:   Documentation/devicetree/bindings/arm/coresight.txt
> >  F:   Documentation/devicetree/bindings/arm/coresight-cpu-debug.txt
> > +F:   Documentation/devicetree/bindings/arm/coresight-cti.yaml
> >  F:   Documentation/ABI/testing/sysfs-bus-coresight-devices-*
> >  F:   tools/perf/arch/arm/util/pmu.c
> >  F:   tools/perf/arch/arm/util/auxtrace.c
> > diff --git a/include/dt-bindings/arm/coresight-cti-dt.h b/include/dt-bindings/arm/coresight-cti-dt.h
> > new file mode 100644
> > index 000000000000..61e7bdf8ea6e
> > --- /dev/null
> > +++ b/include/dt-bindings/arm/coresight-cti-dt.h
> > @@ -0,0 +1,37 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * This header provides constants for the defined trigger signal
> > + * types on CoreSight CTI.
> > + */
> > +
> > +#ifndef _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
> > +#define _DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H
> > +
> > +#define GEN_IO               0
> > +#define GEN_INTREQ   1
> > +#define GEN_INTACK   2
> > +#define GEN_HALTREQ  3
> > +#define GEN_RESTARTREQ       4
> > +#define PE_EDBGREQ   5
> > +#define PE_DBGRESTART        6
> > +#define PE_CTIIRQ    7
> > +#define PE_PMUIRQ    8
> > +#define PE_DBGTRIGGER        9
> > +#define ETM_EXTOUT   10
> > +#define ETM_EXTIN    11
> > +#define SNK_FULL     12
> > +#define SNK_ACQCOMP  13
> > +#define SNK_FLUSHCOMP        14
> > +#define SNK_FLUSHIN  15
> > +#define SNK_TRIGIN   16
> > +#define STM_ASYNCOUT 17
> > +#define STM_TOUT_SPTE        18
> > +#define STM_TOUT_SW  19
> > +#define STM_TOUT_HETE        20
> > +#define STM_HWEVENT  21
> > +#define ELA_TSTART   22
> > +#define ELA_TSTOP    23
> > +#define ELA_DBGREQ   24
> > +#define CTI_TRIG_MAX 25
> > +
> > +#endif /*_DT_BINDINGS_ARM_CORESIGHT_CTI_DT_H */
> > --
> > 2.17.1
> >



-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions.
  2019-11-28 18:38   ` Suzuki Kuruppassery Poulose
@ 2019-11-29 13:57     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-11-29 13:57 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi Suzuki,

On Thu, 28 Nov 2019 at 18:38, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> Hi Mike,
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > Adds new coresight-cti.yaml file describing the bindings required to define
> > CTI in the device trees.
> >
> > Adds an include file to dt-bindings/arm to define constants describing
> > common signal functionality used in CoreSight and generic usage.
>
> The documentation looks really nice and helpful. Some very minor nits
> below.
>
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
>
> > ---
> >   .../bindings/arm/coresight-cti.yaml           | 303 ++++++++++++++++++
> >   .../devicetree/bindings/arm/coresight.txt     |   7 +
> >   MAINTAINERS                                   |   2 +
> >   include/dt-bindings/arm/coresight-cti-dt.h    |  37 +++
> >   4 files changed, 349 insertions(+)
> >   create mode 100644 Documentation/devicetree/bindings/arm/coresight-cti.yaml
> >   create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h
> >
> > diff --git a/Documentation/devicetree/bindings/arm/coresight-cti.yaml b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> > new file mode 100644
> > index 000000000000..882c72f1c798
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
> > @@ -0,0 +1,303 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +# Copyright 2019 Linaro Ltd.
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/arm/coresight-cti.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: ARM Coresight Cross Trigger Interface (CTI) device.
> > +
> > +description: |
> > +  The CoreSight Embedded Cross Trigger (ECT) consists of CTI devices connected
> > +  to one or more CoreSight components and/or a CPU, with CTIs interconnected in
> > +  a star topology via the CTM (which is not programmable). The ECT components
>
> nit: CTM is not expanded anywhere here. For the sake of completeness,
> you may do that here.
>
> i.e, s/"a start topology via the CTM"/"a start topology via the Cross
> Trigger Matrix (CTM)"/
>

Agreed - I think the expansion got lost in the many re-arrangement of this doc.

>
> > +  are not part of the trace generation data path and are thus not part of the
> > +  CoreSight graph described in the general CoreSight bindings file
> > +  coresight.txt.
> > +
> > +  The CTI component properties define the connections between the individual
> > +  CTI and the components it is directly connected to, consisting of input and
> > +  output hardware trigger signals. CTIs can have a maximum number of input and
> > +  output hardware trigger signals (8 each for v1 CTI, 32 each for v2 CTI). The
> > +  number is defined at design time, the maximum of each defined in the DEVID
> > +  register.
> > +
> > +  CTIs are interconnected in a star topology via the CTM, using a number of
> > +  programmable channels usually 4, but again implementation defined and
>
> nit: "programmable channels, usually 4, but..." ?
>
OK

> > +  described in the DEVID register. The star topology is not required to be
> > +  described in the bindings as the actual connections are software
> > +  programmable.
> > +
> > +  In general the connections between CTI and components via the trigger signals
> > +  are implementation defined, other than when v8 core and ETM is present.
>
> nite: are implementation defined, *except when they are connected to an
> Arm v8 compatible CPU or an ETM* ?
>
>
Agreed - clearer.

> > +  The v8 architecture defines the required signal connections between CPU core
>
> nit: "The Arm v8"
>
> > +  and CTI, and ETM and CTI, if the ETM if present.
> > +
> > +  When only minimal information is available for the CTI trigger connections,
> > +  then a minimal driver binding can be declare with no explicit trigger
> > +  signals. This will result in the using the DEVID register to set the
> > +  input and output triggers and channels in use. Any user / client
> > +  application will require additional information on the connections
> > +  between the CTI and other components for correct operation. This minimal
> > +  binding may be used when using the Integration Control registers to
> > +  discover connections between CTI and other CoreSight components,
>
> How about "When the CTI trigger connection information is unavailable,
> the driver detects the number of triggers and channels from the DEVID
> register and makes them available. The Integration Control registers
> can be then used to discover the connections for this CTI device
> to other CoreSight components".
>
> Since we recommend the use of the "Integration Control registers", which
> is not normally available unless you play around the code, it will be a
> good idea to metion, what the user needs to do to make the registers
> available. (One more reason to use the CONFIG symbol, makes that
> easier.)
>

Agreed - need to explain the use case for this and implications of
using a minimal binding.

>
> > +
> > +  Certain triggers between CoreSight devices and the CTI have specific types
> > +  and usages. These can be defined along with the signal indexes with the
> > +  constants defined in <dt-bindings/arm/coresight-cti-dt.h>
> > +
> > +  For example a CTI connected to a core will usually have a DBGREQ signal. This
> > +  is defined in the binding as type PE_EDBGREQ. These types will appear in an
> > +  optional array alongside the signal indexes. Omitting types will default all
> > +  signals to GEN_IO.
> > +
> > +  Note that some hardware trigger signals can be connected to non-CoreSight
> > +  components (e.g. UART etc) depending on hardware implementation.
> > +
> > +maintainers:
> > +  - Mike Leach <mike.leach@linaro.org>
> > +
> > +allOf:
> > +  - $ref: /schemas/arm/primecell.yaml#
> > +
> > +# Need a custom select here or 'arm,primecell' will match on lots of nodes
> > +select:
> > +  properties:
> > +    compatible:
> > +      contains:
> > +        enum:
> > +          - arm,coresight-cti
> > +  required:
> > +    - compatible
> > +
> > +properties:
> > +  $nodename:
> > +    pattern: "^cti(@[0-9a-f,]+)*$"
> > +  compatible:
> > +    items:
> > +      - const: arm,coresight-cti
> > +      - const: arm,primecell
> > +
> > +  reg:
> > +    items:
> > +      - description: device programming registers
> > +
> > +  arm,cti-v8-arch:
>
> If possible, please could we make this :
>
> "arm,cti-arm-v8-architected"
>
> to be more meaning ful ?
>

Per my comments to Rob, the v8-cti case will be a compatible option,
so this will disappear as an attribute.

> > +    type: boolean
> > +    description:
> > +      This CTI follows the v8 architecturally mandated layout for a CTI.
> > +      Bindings declaring this must declare a cpu, and optionally a single
> > +      arm,cs-dev-assoc may be present to define an attached ETM. No additional
> > +      trig-conns nodes are permitted. The driver will build a connection model
> > +      according to architectural requirements. This will include a filter on
> > +      the CPU dbgreq signal as described above.
> > +
> > +  cpu:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/phandle
> > +    description: Handle to cpu this device is associated with.
> > +
> > +  arm,cti-ctm-id:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/uint32
> > +    description:
> > +      Defines the CTM this CTI is connected to, in large systems with multiple
> > +      separate CTI/CTM nets. Typically multi-socket systems where the CTM is
> > +      propagated between sockets.
> > +
> > +  arm,cs-dev-assoc:
> > +    allOf:
> > +      - $ref: /schemas/types.yaml#/definitions/phandle
> > +    description:
> > +      defines a phandle reference to an associated CoreSight trace device.
> > +      When the associated trace device is enabled, then the respective CTI
> > +      will be enabled. Use in a trig-conns node, or in CTI base node when
> > +      arm,cti-v8-arch present. If the associated device has not been registered
> > +      then the node name will be stored as the connection name for later
> > +      resolution. If the associated device is not a CoreSight device or not
> > +      registered then the node name will remain the connection name and
> > +      automatic enabling will not occur.
> > +
> > +patternProperties:
> > +  '^trig_conns@[0-9]+$':
>
> I understand these bindings have been around for quite long and is too
> late to make any changes. So, feel free to ignore this suggestion below
> and I am perfectly fine with it.
>
> --- Begin silly comments Or Skip to DONE ----
>
> Could we make the property names a bit more obvious ? Since they are
> supposed to be written by other people (unlike our variable names), it
> always makes sense to have expanded, meaningful names:
>
> s/trig_conns@/triggers@ ?
>
> s/arm,trig-{in,out}-sigs/arm,cti-{in,out}-triggers
> s/arm,trig-{in,out}-types/arm,cti-{in,out}-trigger-types
>
> "arm,trig-xxx" property name doesn't really imply that it is for cti.
> So, the above changes makes it explicit and more reader friendly.
>
> > +    type: object
> > +    description:
> > +      A trigger connections child node which describes the trigger signals
> > +      between this CTI and another hardware device. This device may be a CPU,
> > +      CoreSight device, any other hardware device or simple external IO lines.
> > +      The connection may have both input and output triggers, or only one or the
> > +      other.
> > +
> > +    properties:
> > +
> > +      arm,trig-in-sigs:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of CTI trigger in signal numbers in use by a trig-conns node.
> > +
> > +      arm,trig-in-types:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of constants representing the types for the CTI trigger in
> > +          signals. Types in this array match to the corresponding signal in the
> > +          arm,trig-in-sigs array. If the -types array is smaller, or omitted
> > +          completely, then the types will default to GEN_IO.
> > +
> > +      arm,trig-out-sigs:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of CTI trigger out signal numbers in use by a trig-conns node.
> > +
> > +      arm,trig-out-types:
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of constants representing the types for the CTI trigger out
> > +          signals. Types in this array match to the corresponding signal
> > +          in the arm,trig-out-sigs array. If the "-types" array is smaller,
> > +          or omitted completely, then the types will default to GEN_IO.
> > +
> > +      arm,trig-filters:
>
> arm,cti-trigger-filters ?
>
> > +        allOf:
> > +          - $ref: /schemas/types.yaml#/definitions/uint32-array
> > +        minItems: 1
> > +        maxItems: 32
> > +        description:
> > +          List of CTI trigger out signals that will be blocked from becoming
> > +          active, unless filtering is disabled on the driver.
> > +
> > +      arm,trig-conn-name:
>
> arm,cti-trigger-name ?
>
>
> --- DONE or End of silly comments ---
>

I appreciate the comments on naming, but my feeling is to
differentiate between the trigger signals and the trigger connections
group. hence the sub-node has group trig_cons.
I was hoping that users would get that these are CTI related by the
fact that the root node is cti@...

> > +  # Implementation defined CTI - CPU + ETM connections explicitly defined..
> > +  # Shows use of type constants from dt-bindings/arm/coresight-cti-dt.h
> > +  - |
> > +    #include <dt-bindings/arm/coresight-cti-dt.h>
> > +
> > +    cti@858000 {
> > +      compatible = "arm,coresight-cti", "arm,primecell";
> > +      reg = <0x858000 0x1000>;
> > +
> > +      clocks = <&soc_smc50mhz>;
> > +      clock-names = "apb_pclk";
> > +
> > +      arm,cti-ctm-id = <1>;
> > +
> > +      trig-conns@0 {
> > +            arm,trig-in-sigs = <4 5 6 7>;
> > +            arm,trig-in-types = <ETM_EXTOUT
> > +                                 ETM_EXTOUT
> > +                                 ETM_EXTOUT
> > +                                 ETM_EXTOUT>;
> > +            arm,trig-out-sigs = <4 5 6 7>;
> > +            arm,trig-out-types = <ETM_EXTIN
> > +                                  ETM_EXTIN
> > +                                  ETM_EXTIN
> > +                                  ETM_EXTIN>;
> > +            arm,cs-dev-assoc = <&etm0>;
> > +      };
> > +
> > +      trig-conns@1 {
> > +            cpu = <&CPU0>;
> > +            arm,trig-in-sigs = <0 1>;
> > +            arm,trig-in-types = <PE_DBGTRIGGER
> > +                                 PE_PMUIRQ>;
> > +            arm,trig-out-sigs=<0 1 2 >;
> > +            arm,trig-out-types = <PE_EDBGREQ
> > +                                  PE_DBGRESTART
> > +                                  PE_CTIIRQ>;
> > +
> > +            arm,trig-filters = <0>;
> > +      };
> > +    };
> > +  # Implementation defined CTI - none CoreSight component connections.
>
> nit: s/none/non ?
>

OK.

> Rest looks fine to me.
>
> Suzuki

Thanks

Mike

-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions.
  2019-11-29 13:50     ` Mike Leach
@ 2019-11-29 14:12       ` Suzuki Kuruppassery Poulose
  0 siblings, 0 replies; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-29 14:12 UTC (permalink / raw)
  To: Mike Leach, Rob Herring
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

On 29/11/2019 13:50, Mike Leach wrote:
> Hi Rob,
> 
> On Fri, 22 Nov 2019 at 23:33, Rob Herring <robh@kernel.org> wrote:
>>
>> On Tue, Nov 19, 2019 at 11:19:03PM +0000, Mike Leach wrote:
>>> Adds new coresight-cti.yaml file describing the bindings required to define
>>> CTI in the device trees.
>>>
>>> Adds an include file to dt-bindings/arm to define constants describing
>>> common signal functionality used in CoreSight and generic usage.
>>>
>>> Signed-off-by: Mike Leach <mike.leach@linaro.org>
>>> ---
>>>   .../bindings/arm/coresight-cti.yaml           | 303 ++++++++++++++++++
>>>   .../devicetree/bindings/arm/coresight.txt     |   7 +
>>>   MAINTAINERS                                   |   2 +
>>>   include/dt-bindings/arm/coresight-cti-dt.h    |  37 +++
>>>   4 files changed, 349 insertions(+)
>>>   create mode 100644 Documentation/devicetree/bindings/arm/coresight-cti.yaml
>>>   create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/coresight-cti.yaml b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
>>> new file mode 100644
>>> index 000000000000..882c72f1c798
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/arm/coresight-cti.yaml
>>> @@ -0,0 +1,303 @@
>>> +# SPDX-License-Identifier: GPL-2.0
>>
>> Dual license new bindings please:
>>
>> (GPL-2.0-only OR BSD-2-Clause)
>>
> OK.
> 
>>> +# Copyright 2019 Linaro Ltd.
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/arm/coresight-cti.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: ARM Coresight Cross Trigger Interface (CTI) device.
>>> +
>>> +description: |
>>> +  The CoreSight Embedded Cross Trigger (ECT) consists of CTI devices connected
>>> +  to one or more CoreSight components and/or a CPU, with CTIs interconnected in
>>> +  a star topology via the CTM (which is not programmable). The ECT components
>>> +  are not part of the trace generation data path and are thus not part of the
>>> +  CoreSight graph described in the general CoreSight bindings file
>>> +  coresight.txt.
>>> +
>>> +  The CTI component properties define the connections between the individual
>>> +  CTI and the components it is directly connected to, consisting of input and
>>> +  output hardware trigger signals. CTIs can have a maximum number of input and
>>> +  output hardware trigger signals (8 each for v1 CTI, 32 each for v2 CTI). The
>>> +  number is defined at design time, the maximum of each defined in the DEVID
>>> +  register.
>>> +
>>> +  CTIs are interconnected in a star topology via the CTM, using a number of
>>> +  programmable channels usually 4, but again implementation defined and
>>> +  described in the DEVID register. The star topology is not required to be
>>> +  described in the bindings as the actual connections are software
>>> +  programmable.
>>> +
>>> +  In general the connections between CTI and components via the trigger signals
>>> +  are implementation defined, other than when v8 core and ETM is present.
>>> +  The v8 architecture defines the required signal connections between CPU core
>>> +  and CTI, and ETM and CTI, if the ETM if present.
>>> +
>>> +  When only minimal information is available for the CTI trigger connections,
>>> +  then a minimal driver binding can be declare with no explicit trigger
>>> +  signals. This will result in the using the DEVID register to set the
>>> +  input and output triggers and channels in use. Any user / client
>>> +  application will require additional information on the connections
>>> +  between the CTI and other components for correct operation. This minimal
>>> +  binding may be used when using the Integration Control registers to
>>> +  discover connections between CTI and other CoreSight components,
>>> +
>>> +  Certain triggers between CoreSight devices and the CTI have specific types
>>> +  and usages. These can be defined along with the signal indexes with the
>>> +  constants defined in <dt-bindings/arm/coresight-cti-dt.h>
>>> +
>>> +  For example a CTI connected to a core will usually have a DBGREQ signal. This
>>> +  is defined in the binding as type PE_EDBGREQ. These types will appear in an
>>> +  optional array alongside the signal indexes. Omitting types will default all
>>> +  signals to GEN_IO.
>>> +
>>> +  Note that some hardware trigger signals can be connected to non-CoreSight
>>> +  components (e.g. UART etc) depending on hardware implementation.
>>> +
>>> +maintainers:
>>> +  - Mike Leach <mike.leach@linaro.org>
>>> +
>>> +allOf:
>>> +  - $ref: /schemas/arm/primecell.yaml#
>>> +
>>> +# Need a custom select here or 'arm,primecell' will match on lots of nodes
>>> +select:
>>> +  properties:
>>> +    compatible:
>>> +      contains:
>>> +        enum:
>>> +          - arm,coresight-cti
>>> +  required:
>>> +    - compatible
>>> +
>>> +properties:
>>> +  $nodename:
>>> +    pattern: "^cti(@[0-9a-f,]+)*$"
>>
>> Unit address should not be optional nor have a comma.
>>
> 
> Will fix.
> 
>>> +  compatible:
>>> +    items:
>>> +      - const: arm,coresight-cti
>>> +      - const: arm,primecell
>>> +
>>> +  reg:
>>> +    items:
>>> +      - description: device programming registers
>>
>> Just "maxItems: 1" is sufficient.
>>
> 
> OK
> 
>>> +
>>> +  arm,cti-v8-arch:
>>> +    type: boolean
>>> +    description:
>>> +      This CTI follows the v8 architecturally mandated layout for a CTI.
>>
>> Seems like the compatible or primecell ID registers should be used for
>> something like this.
>>
> 
> Unfortunately it is possible and has happened that the same primecell
> regs for a CTI connected to a v8 core and one that is used as a
> general system CTI appear in the same system.
> There is no architectural requirement on the CTI to indicate that its
> external connections are as per v8 architecture spec when connected to
>   a PE/ETM combo.
> 
> Therefore a compatible "arm,coresight-cti-v8" would seem the best
> route. I'll update the compatible portion of the schema and handling
> code accordingly.

Looks sensible to me. However, please be aware that the coresight
devices are triggered via the AMBA bus probe. So, you may have to scan
the list of compatibles for this device to figure out, if this is really
v8-compatble.

Cheers
Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI.
  2019-11-25 21:22   ` Mathieu Poirier
@ 2019-11-29 14:16     ` Suzuki Kuruppassery Poulose
  2019-11-29 21:11       ` Mathieu Poirier
  0 siblings, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-29 14:16 UTC (permalink / raw)
  To: Mathieu Poirier, Mike Leach
  Cc: coresight, linux-arm-kernel, devicetree, linux-doc

On 25/11/2019 21:22, Mathieu Poirier wrote:
> On Tue, Nov 19, 2019 at 11:19:05PM +0000, Mike Leach wrote:
>> Adds support for CTIs whose connections are implementation defined at
>> hardware design time, and not constrained by v8 architecture.
>>
>> These CTIs have no standard connection setup, all the settings have to
>> be defined in the device tree files. The patch creates a set of connections
>> and trigger signals based on the information provided.
>>
>> Signed-off-by: Mike Leach <mike.leach@linaro.org>
>> ---
>>   .../coresight/coresight-cti-platform.c        | 250 +++++++++++++++++-
>>   .../hwtracing/coresight/coresight-cti-sysfs.c |  11 +
>>   2 files changed, 257 insertions(+), 4 deletions(-)

>> +static int cti_plat_create_impdef_connections(struct device *dev,
>> +					      struct cti_drvdata *drvdata)
>> +{
>> +	int rc = 0;
>> +	struct fwnode_handle *fwnode = dev_fwnode(dev);
>> +	struct fwnode_handle *child = NULL;
>> +
>> +	if (IS_ERR_OR_NULL(fwnode))
>> +		return -EINVAL;
>> +
>> +	fwnode_for_each_child_node(fwnode, child) {
>> +		if (cti_plat_node_name_eq(child, CTI_DT_CONNS))
>> +			rc = cti_plat_create_connection(dev, drvdata, child);
>> +		if (rc != 0)
>> +			break;
>> +	}
>> +	fwnode_handle_put(child);
> 
> As far as I can tell we don't need to call fwnode_handle_put()?

Actually we do, if we break the scan in between, at least for of_nodes.
I had to literally look it down all the way down to confirm this.

So for CONFIG_OF it ends up in of_get_next_available_child(), which
drops the ref on "prev" and grabs the "next". So in case we break
the loop, we must drop the ref on the child. Otherwise, the last
result would be NULL, which would have dropped the ref on the "last"
valid entry. And this is harmless with a NULL ptr.

Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI.
  2019-11-19 23:19 ` [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI Mike Leach
  2019-11-25 21:22   ` Mathieu Poirier
@ 2019-11-29 14:18   ` Suzuki Kuruppassery Poulose
  2019-12-03 14:05     ` Mike Leach
  1 sibling, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-29 14:18 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

On 19/11/2019 23:19, Mike Leach wrote:
> Adds support for CTIs whose connections are implementation defined at
> hardware design time, and not constrained by v8 architecture.
> 
> These CTIs have no standard connection setup, all the settings have to
> be defined in the device tree files. The patch creates a set of connections
> and trigger signals based on the information provided.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>   .../coresight/coresight-cti-platform.c        | 250 +++++++++++++++++-
>   .../hwtracing/coresight/coresight-cti-sysfs.c |  11 +
>   2 files changed, 257 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
> index 790dd30b85f5..9c1ff432b487 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-platform.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
> @@ -13,9 +13,19 @@
>   #define NR_V8PE_OUT_SIGS	3
>   #define NR_V8ETM_INOUT_SIGS	4
>   
> +/* CTI device tree trigger connection node keyword */
> +#define CTI_DT_CONNS		"trig-conns"
> +
>   /* CTI device tree connection property keywords */
>   #define CTI_DT_V8ARCH		"arm,cti-v8-arch"
>   #define CTI_DT_CSDEV_ASSOC	"arm,cs-dev-assoc"
> +#define CTI_DT_TRIGIN_SIGS	"arm,trig-in-sigs"
> +#define CTI_DT_TRIGOUT_SIGS	"arm,trig-out-sigs"
> +#define CTI_DT_TRIGIN_TYPES	"arm,trig-in-types"
> +#define CTI_DT_TRIGOUT_TYPES	"arm,trig-out-types"
> +#define CTI_DT_FILTER_OUT_SIGS	"arm,trig-filters"
> +#define CTI_DT_CONN_NAME	"arm,trig-conn-name"
> +#define CTI_DT_CTM_ID		"arm,cti-ctm-id"
>   
>   /*
>    * Find a registered coresight device from a device fwnode.
> @@ -68,6 +78,12 @@ static const char *of_cti_get_node_name(const struct device_node *node)
>   		return node->full_name;
>   	return "unknown";
>   }
> +
> +static bool of_cti_node_name_eq(const struct device_node *node,
> +				const char *name)
> +{
> +	return of_node_name_eq(node, name);
> +}
>   #else
>   static int of_cti_get_cpu_at_node(const struct device_node *node)
>   {
> @@ -78,6 +94,12 @@ static const char *of_cti_get_node_name(const struct device_node *node)
>   {
>   	return "unknown";
>   }
> +
> +static bool of_cti_node_name_eq(const struct device_node *node,
> +				const char *name)
> +{
> +	return false;
> +}
>   #endif

nit: You don't need this wrapper of_node_name_eq() is already defined to
return false for !CONFIG_OF.


>   
>   static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
> @@ -94,6 +116,14 @@ static const char *cti_plat_get_node_name(struct fwnode_handle *fwnode)
>   	return "unknown";
>   }
>   
> +static bool cti_plat_node_name_eq(struct fwnode_handle *fwnode,
> +				  const char *name)
> +{
> +	if (is_of_node(fwnode))
> +		return of_cti_node_name_eq(to_of_node(fwnode), name);

As mentioned above you could simply use of_node_name_eq() here.

> +	return false;
> +}
> +
>   static int cti_plat_create_v8_etm_connection(struct device *dev,
>   					     struct cti_drvdata *drvdata)
>   {
> @@ -205,6 +235,214 @@ static int cti_plat_create_v8_connections(struct device *dev,
>   	return ret;
>   }
>   
> +static int cti_plat_count_sig_elements(const struct fwnode_handle *fwnode,
> +				       const char *name)
> +{
> +	int nr_elem = fwnode_property_count_u32(fwnode, name);
> +
> +	return (nr_elem < 0 ? 0 : nr_elem);
> +}
> +
> +static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp,
> +				    const struct fwnode_handle *fwnode,
> +				    const char *grp_name)
> +{
> +	int idx, err = 0;
> +	u32 *values;
> +
> +	if (!tgrp->nr_sigs)
> +		return 0;
> +
> +	values = kcalloc(tgrp->nr_sigs, sizeof(u32), GFP_KERNEL);
> +	if (!values)
> +		return -ENOMEM;
> +
> +	err = fwnode_property_read_u32_array(fwnode, grp_name,
> +					     values, tgrp->nr_sigs);
> +
> +	if (!err) {
> +		/* set the signal usage mask */
> +		for (idx = 0; idx < tgrp->nr_sigs; idx++)
> +			tgrp->used_mask |= BIT(values[idx]);
> +	}
> +
> +	kfree(values);
> +	return err;
> +}
> +
> +static int cti_plat_read_trig_types(struct cti_trig_grp *tgrp,
> +				    const struct fwnode_handle *fwnode,
> +				    const char *type_name)
> +{
> +	int items, used = 0, err = 0, nr_sigs;
> +	u32 *values = NULL, i;
> +
> +	/* allocate an array according to number of signals in connection */
> +	nr_sigs = tgrp->nr_sigs;
> +	if (!nr_sigs)
> +		return 0;
> +
> +	/* see if any types have been included in the device description */
> +	items = cti_plat_count_sig_elements(fwnode, type_name);
> +	if (items > nr_sigs)
> +		return -EINVAL;
> +
> +	/* need an array to store the values iff there are any */
> +	if (items) {
> +		values = kcalloc(items, sizeof(u32), GFP_KERNEL);
> +		if (!values)
> +			return -ENOMEM;
> +
> +		err = fwnode_property_read_u32_array(fwnode, type_name,
> +						     values, items);
> +		if (err)
> +			goto read_trig_types_out;
> +	}
> +
> +	/*
> +	 * Match type id to signal index, 1st type to 1st index etc.
> +	 * If fewer types than signals default remainder to GEN_IO.
> +	 */
> +	for (i = 0; i < nr_sigs; i++) {
> +		if (used < items) {
> +			tgrp->sig_types[i] =
> +				values[i] < CTI_TRIG_MAX ? values[i] : GEN_IO;
> +			used++;

Do we really need "used" here ? Couldn't this be :

		if (i < items) {

		}

> +		} else {

   + 	 		/* Mark the undefined connections as GEN_IO */ ?

> +			tgrp->sig_types[i] = GEN_IO;
> +		}
> +	}

...

> +
> +	/* read the connection name if set - may be overridden by later */
> +	fwnode_property_read_string(fwnode, CTI_DT_CONN_NAME, &assoc_name);
> +
> +	/* associated cpu ? */
> +	cpuid = cti_plat_get_cpu_at_node(fwnode);
> +	if (cpuid >= 0) {
> +		drvdata->ctidev.cpu = cpuid;
> +		scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid);
> +		assoc_name = cpu_name_str;
> +	} else {
> +		/* associated device ? */
> +		cs_fwnode = fwnode_find_reference(fwnode,
> +						  CTI_DT_CSDEV_ASSOC, 0);

> +		if (!IS_ERR_OR_NULL(cs_fwnode)) {

--- Cut - here --
> +			csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
> +			if (csdev) /* use device name if csdev found */
> +				assoc_name = dev_name(&csdev->dev);
> +			else  /* otherwise node name for later association */
> +				assoc_name = cti_plat_get_node_name(cs_fwnode);

--- end - here --

I believe we do this for arm_v8 architected connections too. May be make
this a helper ?

> +			fwnode_handle_put(cs_fwnode);
> +		}
> +	}
> +	/* set up a connection */
> +	err = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name);
> +
> +create_con_err:
> +	return err;
> +}
> +
> +static int cti_plat_create_impdef_connections(struct device *dev,
> +					      struct cti_drvdata *drvdata)
> +{
> +	int rc = 0;
> +	struct fwnode_handle *fwnode = dev_fwnode(dev);
> +	struct fwnode_handle *child = NULL;
> +
> +	if (IS_ERR_OR_NULL(fwnode))
> +		return -EINVAL;
> +
> +	fwnode_for_each_child_node(fwnode, child) {
> +		if (cti_plat_node_name_eq(child, CTI_DT_CONNS))
> +			rc = cti_plat_create_connection(dev, drvdata, child);
> +		if (rc != 0)
> +			break;

minor nit: To make it more obvious :

		if (cti_plat_node_name_eq(child, CTI_DT_CONNS)) {
			rc = cti_plat_create_connection(dev, drvdata,
							child);
			if (rc)
				break;
		}

Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices.
  2019-11-19 23:19 ` [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices Mike Leach
  2019-11-25 22:45   ` Mathieu Poirier
@ 2019-11-29 18:28   ` Suzuki Kuruppassery Poulose
  2019-11-29 21:25     ` Mathieu Poirier
  2019-12-05 16:33     ` Mike Leach
  1 sibling, 2 replies; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-11-29 18:28 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

On 19/11/2019 23:19, Mike Leach wrote:
> The CoreSight subsystem enables a path of devices from source to sink.
> Any CTI devices associated with the path devices must be enabled at the
> same time.
> 
> This patch adds an associated coresight_device element to the main
> coresight device structure, and uses this to create associations between
> the CTI and other devices based on the device tree data. The associated
> device element is used to enable CTI in conjunction with the path elements.
> 
> CTI devices are reference counted so where a single CTI is associated with
> multiple elements on the path, it will be enabled on the first associated
> device enable, and disabled with the last associated device disable.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>   drivers/hwtracing/coresight/coresight-cti.c   | 87 +++++++++++++++++++
>   .../hwtracing/coresight/coresight-platform.c  | 23 +++++
>   drivers/hwtracing/coresight/coresight-priv.h  |  6 ++
>   drivers/hwtracing/coresight/coresight.c       | 58 +++++++++++--
>   include/linux/coresight.h                     |  5 ++
>   5 files changed, 173 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> index 369488dd7b8e..cf116463149a 100644
> --- a/drivers/hwtracing/coresight/coresight-cti.c
> +++ b/drivers/hwtracing/coresight/coresight-cti.c
> @@ -440,6 +440,90 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
>   	return err;
>   }
>   
> +/*
> + * Look for a matching connection device name in the list of
> + * connections. If found then swap in the csdev name and return
> + * found.
> + */
> +static bool
> +cti_match_con_name(struct cti_device *ctidev, const char *node_name,
> +		   const char *csdev_name)

Here we actually fixup the name of the connection, rather than simply 
matching it. So it may be apt to rename this to cti_match_fixup_name()

> +{
> +	struct cti_trig_con *trig_con;
> +
> +	list_for_each_entry(trig_con, &ctidev->trig_cons, node) {
> +		if (trig_con->con_dev_name) {
> +			if (!strcmp(node_name, trig_con->con_dev_name)) {

Can there be duplicate node_name's ? Does it make sense to store the 
fwhandle along with the "temporary node_name" to match it later while
fixing up ?

> +				/* match: so swap in csdev name */
> +				kfree(trig_con->con_dev_name);
> +				trig_con->con_dev_name =
> +					kstrdup(csdev_name, GFP_KERNEL);
> +				return true;
> +			}
> +		}
> +	}
> +	return false;
> +}


> +/*
> + * Search the cti list to add an associated CTI into the supplied CS device
> + * This will set the association if CTI declared before the CS device
> + */
> +void cti_add_assoc_to_csdev(struct coresight_device *csdev)
> +{

..

 > +	struct cti_drvdata *ect_item;
 > +	struct cti_device *ctidev;
 > +	const char *node_name = NULL, *csdev_name;
 > +
 > +	/* protect the list */
 > +	mutex_lock(&ect_mutex);
 > +
 > +	/* exit if current is an ECT device.*/
 > +	if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net))
 > +		goto cti_add_done;
 > +
 > +	/* if we didn't find the csdev previously we used the fwnode name */
 > +	node_name = coresight_get_fwnode_name(csdev->dev.parent);

We used "cti_plat_get_node_name()" when we added the name in the
absence of csdev in patch 7, could we not reuse the function here ?

 > +
 > +	if (!node_name)
 > +		goto cti_add_done;
 > +
 > +	/* this is the name we want to use for the association */
 > +	csdev_name = dev_name(&csdev->dev);


> +
> +	/* for each CTI in list... */
> +	list_for_each_entry(ect_item, &ect_net, node) {
> +		ctidev = &ect_item->ctidev;
> +		if (cti_match_con_name(ctidev, node_name, csdev_name)) {
> +			/*
> +			 * if we found a matching name then update the
> +			 * association pointers.
> +			 */
> +			csdev->ect_dev = ect_item->csdev;
> +			goto cti_add_done;

			break; instead ?

> +		}
> +	}
> +cti_add_done:
> +	mutex_unlock(&ect_mutex);
> +}
> +EXPORT_SYMBOL_GPL(cti_add_assoc_to_csdev);
> +
> +/*
> + * Update the cross references where the associated device was found
> + * while we were building the connection info. This will occur if the
> + * assoc device was registered before the CTI.
> + */
> +static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)
> +{
> +	struct cti_trig_con *tc;
> +	struct cti_device *ctidev = &drvdata->ctidev;
> +
> +	list_for_each_entry(tc, &ctidev->trig_cons, node) {
> +		if (tc->con_dev)
> +			tc->con_dev->ect_dev = drvdata->csdev;
> +	}

Does this need to take the coresight_mutex to avoid racing against
a coresight_enable_path() ? Though this may be fine as long as the
CTI driver detects that that device was not enabled.

Also, it looks like we have a potential issue with perf vs sysfs mode.
The perf mode doesn't seem to take the coresight_mutex, for
build_path/enable_path operations. This is outside the scope of this
series though.

> +}
> +
>   /** cti ect operations **/
>   int cti_enable(struct coresight_device *csdev)
>   {
> @@ -574,6 +658,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
>   	drvdata->csdev_release = drvdata->csdev->dev.release;
>   	drvdata->csdev->dev.release = cti_device_release;
>   
> +	/* set any cross references */
> +	cti_update_conn_xrefs(drvdata);
> +
    	/* all done - dec pm refcount */
>   	pm_runtime_put(&adev->dev);
>   	dev_info(&drvdata->csdev->dev, "CTI initialized\n");
> diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
> index 3c5bee429105..6721cb1af5fe 100644
> --- a/drivers/hwtracing/coresight/coresight-platform.c
> +++ b/drivers/hwtracing/coresight/coresight-platform.c
> @@ -293,6 +293,12 @@ static int of_get_coresight_platform_data(struct device *dev,
>   
>   	return 0;
>   }
> +
> +static inline const char *of_coresight_get_node_name(struct device *dev)
> +{
> +	return dev->of_node->full_name;
> +}
> +
>   #else
>   static inline int
>   of_get_coresight_platform_data(struct device *dev,
> @@ -305,6 +311,11 @@ static inline int of_coresight_get_cpu(struct device *dev)
>   {
>   	return -ENODEV;
>   }
> +
> +static inline const char *of_coresight_get_node_name(struct device *dev)
> +{
> +	return NULL;
> +}
>   #endif
>   
>   #ifdef CONFIG_ACPI
> @@ -766,6 +777,18 @@ static inline int acpi_coresight_get_cpu(struct device *dev)
>   }
>   #endif
>   
> +const char *coresight_get_fwnode_name(struct device *dev)

As mentioned above, please could we reuse the name helper we used
during the insertion rather than introducing a new wrapper which
effectively does the same thing ?

> +{
> +	const char *node_name = NULL;
> +	struct fwnode_handle *fwnode = dev_fwnode(dev);
> +
> +	if (is_of_node(fwnode))
> +		node_name = of_coresight_get_node_name(dev);
> +
> +	return node_name;
> +}
> +EXPORT_SYMBOL_GPL(coresight_get_fwnode_name);

Why does this get exported ? If a following patch needs it, you may
always do that when you need it.


Cheers
Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI.
  2019-11-29 14:16     ` Suzuki Kuruppassery Poulose
@ 2019-11-29 21:11       ` Mathieu Poirier
  0 siblings, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-29 21:11 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Mike Leach, Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION

On Fri, 29 Nov 2019 at 07:16, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 25/11/2019 21:22, Mathieu Poirier wrote:
> > On Tue, Nov 19, 2019 at 11:19:05PM +0000, Mike Leach wrote:
> >> Adds support for CTIs whose connections are implementation defined at
> >> hardware design time, and not constrained by v8 architecture.
> >>
> >> These CTIs have no standard connection setup, all the settings have to
> >> be defined in the device tree files. The patch creates a set of connections
> >> and trigger signals based on the information provided.
> >>
> >> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> >> ---
> >>   .../coresight/coresight-cti-platform.c        | 250 +++++++++++++++++-
> >>   .../hwtracing/coresight/coresight-cti-sysfs.c |  11 +
> >>   2 files changed, 257 insertions(+), 4 deletions(-)
>
> >> +static int cti_plat_create_impdef_connections(struct device *dev,
> >> +                                          struct cti_drvdata *drvdata)
> >> +{
> >> +    int rc = 0;
> >> +    struct fwnode_handle *fwnode = dev_fwnode(dev);
> >> +    struct fwnode_handle *child = NULL;
> >> +
> >> +    if (IS_ERR_OR_NULL(fwnode))
> >> +            return -EINVAL;
> >> +
> >> +    fwnode_for_each_child_node(fwnode, child) {
> >> +            if (cti_plat_node_name_eq(child, CTI_DT_CONNS))
> >> +                    rc = cti_plat_create_connection(dev, drvdata, child);
> >> +            if (rc != 0)
> >> +                    break;
> >> +    }
> >> +    fwnode_handle_put(child);
> >
> > As far as I can tell we don't need to call fwnode_handle_put()?
>
> Actually we do, if we break the scan in between, at least for of_nodes.
> I had to literally look it down all the way down to confirm this.
>
> So for CONFIG_OF it ends up in of_get_next_available_child(), which
> drops the ref on "prev" and grabs the "next". So in case we break
> the loop, we must drop the ref on the child.

Well spotted.

> Otherwise, the last
> result would be NULL, which would have dropped the ref on the "last"
> valid entry. And this is harmless with a NULL ptr.
>
> Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices.
  2019-11-29 18:28   ` Suzuki Kuruppassery Poulose
@ 2019-11-29 21:25     ` Mathieu Poirier
  2019-12-05 16:33     ` Mike Leach
  1 sibling, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-11-29 21:25 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Mike Leach, Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION

On Fri, 29 Nov 2019 at 11:28, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > The CoreSight subsystem enables a path of devices from source to sink.
> > Any CTI devices associated with the path devices must be enabled at the
> > same time.
> >
> > This patch adds an associated coresight_device element to the main
> > coresight device structure, and uses this to create associations between
> > the CTI and other devices based on the device tree data. The associated
> > device element is used to enable CTI in conjunction with the path elements.
> >
> > CTI devices are reference counted so where a single CTI is associated with
> > multiple elements on the path, it will be enabled on the first associated
> > device enable, and disabled with the last associated device disable.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >   drivers/hwtracing/coresight/coresight-cti.c   | 87 +++++++++++++++++++
> >   .../hwtracing/coresight/coresight-platform.c  | 23 +++++
> >   drivers/hwtracing/coresight/coresight-priv.h  |  6 ++
> >   drivers/hwtracing/coresight/coresight.c       | 58 +++++++++++--
> >   include/linux/coresight.h                     |  5 ++
> >   5 files changed, 173 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> > index 369488dd7b8e..cf116463149a 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti.c
> > @@ -440,6 +440,90 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
> >       return err;
> >   }
> >
> > +/*
> > + * Look for a matching connection device name in the list of
> > + * connections. If found then swap in the csdev name and return
> > + * found.
> > + */
> > +static bool
> > +cti_match_con_name(struct cti_device *ctidev, const char *node_name,
> > +                const char *csdev_name)
>
> Here we actually fixup the name of the connection, rather than simply
> matching it. So it may be apt to rename this to cti_match_fixup_name()
>
> > +{
> > +     struct cti_trig_con *trig_con;
> > +
> > +     list_for_each_entry(trig_con, &ctidev->trig_cons, node) {
> > +             if (trig_con->con_dev_name) {
> > +                     if (!strcmp(node_name, trig_con->con_dev_name)) {
>
> Can there be duplicate node_name's ? Does it make sense to store the
> fwhandle along with the "temporary node_name" to match it later while
> fixing up ?

I think we're fine here - CS devices have bidirectional connections
that are checked by the DTC.  You get a bitter complaint if two CS
nodes have the same value.

>
> > +                             /* match: so swap in csdev name */
> > +                             kfree(trig_con->con_dev_name);
> > +                             trig_con->con_dev_name =
> > +                                     kstrdup(csdev_name, GFP_KERNEL);
> > +                             return true;
> > +                     }
> > +             }
> > +     }
> > +     return false;
> > +}
>
>
> > +/*
> > + * Search the cti list to add an associated CTI into the supplied CS device
> > + * This will set the association if CTI declared before the CS device
> > + */
> > +void cti_add_assoc_to_csdev(struct coresight_device *csdev)
> > +{
>
> ..
>
>  > +    struct cti_drvdata *ect_item;
>  > +    struct cti_device *ctidev;
>  > +    const char *node_name = NULL, *csdev_name;
>  > +
>  > +    /* protect the list */
>  > +    mutex_lock(&ect_mutex);
>  > +
>  > +    /* exit if current is an ECT device.*/
>  > +    if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net))
>  > +            goto cti_add_done;
>  > +
>  > +    /* if we didn't find the csdev previously we used the fwnode name */
>  > +    node_name = coresight_get_fwnode_name(csdev->dev.parent);
>
> We used "cti_plat_get_node_name()" when we added the name in the
> absence of csdev in patch 7, could we not reuse the function here ?
>
>  > +
>  > +    if (!node_name)
>  > +            goto cti_add_done;
>  > +
>  > +    /* this is the name we want to use for the association */
>  > +    csdev_name = dev_name(&csdev->dev);
>
>
> > +
> > +     /* for each CTI in list... */
> > +     list_for_each_entry(ect_item, &ect_net, node) {
> > +             ctidev = &ect_item->ctidev;
> > +             if (cti_match_con_name(ctidev, node_name, csdev_name)) {
> > +                     /*
> > +                      * if we found a matching name then update the
> > +                      * association pointers.
> > +                      */
> > +                     csdev->ect_dev = ect_item->csdev;
> > +                     goto cti_add_done;
>
>                         break; instead ?
>
> > +             }
> > +     }
> > +cti_add_done:
> > +     mutex_unlock(&ect_mutex);
> > +}
> > +EXPORT_SYMBOL_GPL(cti_add_assoc_to_csdev);
> > +
> > +/*
> > + * Update the cross references where the associated device was found
> > + * while we were building the connection info. This will occur if the
> > + * assoc device was registered before the CTI.
> > + */
> > +static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_trig_con *tc;
> > +     struct cti_device *ctidev = &drvdata->ctidev;
> > +
> > +     list_for_each_entry(tc, &ctidev->trig_cons, node) {
> > +             if (tc->con_dev)
> > +                     tc->con_dev->ect_dev = drvdata->csdev;
> > +     }
>
> Does this need to take the coresight_mutex to avoid racing against
> a coresight_enable_path() ? Though this may be fine as long as the
> CTI driver detects that that device was not enabled.
>
> Also, it looks like we have a potential issue with perf vs sysfs mode.
> The perf mode doesn't seem to take the coresight_mutex, for
> build_path/enable_path operations. This is outside the scope of this
> series though.
>
> > +}
> > +
> >   /** cti ect operations **/
> >   int cti_enable(struct coresight_device *csdev)
> >   {
> > @@ -574,6 +658,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> >       drvdata->csdev_release = drvdata->csdev->dev.release;
> >       drvdata->csdev->dev.release = cti_device_release;
> >
> > +     /* set any cross references */
> > +     cti_update_conn_xrefs(drvdata);
> > +
>         /* all done - dec pm refcount */
> >       pm_runtime_put(&adev->dev);
> >       dev_info(&drvdata->csdev->dev, "CTI initialized\n");
> > diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
> > index 3c5bee429105..6721cb1af5fe 100644
> > --- a/drivers/hwtracing/coresight/coresight-platform.c
> > +++ b/drivers/hwtracing/coresight/coresight-platform.c
> > @@ -293,6 +293,12 @@ static int of_get_coresight_platform_data(struct device *dev,
> >
> >       return 0;
> >   }
> > +
> > +static inline const char *of_coresight_get_node_name(struct device *dev)
> > +{
> > +     return dev->of_node->full_name;
> > +}
> > +
> >   #else
> >   static inline int
> >   of_get_coresight_platform_data(struct device *dev,
> > @@ -305,6 +311,11 @@ static inline int of_coresight_get_cpu(struct device *dev)
> >   {
> >       return -ENODEV;
> >   }
> > +
> > +static inline const char *of_coresight_get_node_name(struct device *dev)
> > +{
> > +     return NULL;
> > +}
> >   #endif
> >
> >   #ifdef CONFIG_ACPI
> > @@ -766,6 +777,18 @@ static inline int acpi_coresight_get_cpu(struct device *dev)
> >   }
> >   #endif
> >
> > +const char *coresight_get_fwnode_name(struct device *dev)
>
> As mentioned above, please could we reuse the name helper we used
> during the insertion rather than introducing a new wrapper which
> effectively does the same thing ?
>
> > +{
> > +     const char *node_name = NULL;
> > +     struct fwnode_handle *fwnode = dev_fwnode(dev);
> > +
> > +     if (is_of_node(fwnode))
> > +             node_name = of_coresight_get_node_name(dev);
> > +
> > +     return node_name;
> > +}
> > +EXPORT_SYMBOL_GPL(coresight_get_fwnode_name);
>
> Why does this get exported ? If a following patch needs it, you may
> always do that when you need it.
>
>
> Cheers
> Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 09/14] coresight: cti: Add connection information to sysfs
  2019-11-19 23:19 ` [PATCH v5 09/14] coresight: cti: Add connection information to sysfs Mike Leach
  2019-11-27 18:09   ` Mathieu Poirier
@ 2019-12-02  9:47   ` Suzuki Kuruppassery Poulose
  2019-12-06 16:24     ` Mike Leach
  1 sibling, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-12-02  9:47 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

On 19/11/2019 23:19, Mike Leach wrote:
> Dynamically adds sysfs attributes for all connections defined in the CTI.
> 
> Each connection has a triggers<N> sub-directory with name, in_signals,
> in_types, out_signals and out_types as read-only parameters in the
> directory. in_ or out_ parameters may be omitted if there are no in or
> out signals for the connection.
> 
> Additionally each device has a nr_cons in the connections sub-directory.
> 
> This allows clients to explore the connection and trigger signal details
> without needing to refer to device tree or specification of the device.
> 
> Standardised type information is provided for certain common functions -
> e.g. snk_full for a trigger from a sink indicating full. Otherwise type
> defaults to genio.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>   .../hwtracing/coresight/coresight-cti-sysfs.c | 376 +++++++++++++++++-
>   drivers/hwtracing/coresight/coresight-cti.c   |  13 +-
>   drivers/hwtracing/coresight/coresight-cti.h   |  11 +-
>   3 files changed, 396 insertions(+), 4 deletions(-)
> 


The patch looks good overall, some minor comments below.


> diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> index f800402f73da..91986732506f 100644
> --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> @@ -8,6 +8,67 @@


> @@ -818,7 +890,306 @@ static struct attribute *coresight_cti_channel_attrs[] = {
>   	NULL,
>   };
>   
> -/* sysfs groups */
> +/* Create the connections trigger groups and attrs dynamically */
> +/*
> + * Each connection has dynamic group triggers<N> + name, trigin/out sigs/types
> + * attributes, + each device has static nr_trigger_cons giving the number
> + * of groups. e.g. in sysfs:-
> + * /cti_<name>/triggers0
> + * /cti_<name>/triggers1
> + * /cti_<name>/nr_trigger_cons
> + * where nr_trigger_cons = 2
> + */
> +static ssize_t con_name_show(struct device *dev,
> +			     struct device_attribute *attr,
> +			     char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +
> +	return scnprintf(buf, PAGE_SIZE, "%s\n", con->con_dev_name);
> +}
> +
> +static ssize_t trigin_sig_show(struct device *dev,
> +			       struct device_attribute *attr,
> +			       char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *cfg = &drvdata->config;
> +	unsigned long mask = con->con_in->used_mask;
> +
> +	return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
> +}
> +
> +static ssize_t trigout_sig_show(struct device *dev,
> +				struct device_attribute *attr,
> +				char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +	struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> +	struct cti_config *cfg = &drvdata->config;
> +	unsigned long mask = con->con_out->used_mask;
> +
> +	return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
> +}
> +
> +/* convert a sig type id to a name */
> +static const char *
> +cti_sig_type_name(struct cti_trig_con *con, int used_count, bool in)
> +{
> +	int idx = 0;
> +	struct cti_trig_grp *grp = in ? con->con_in : con->con_out;
> +
> +	if (grp->sig_types) {
> +		if (used_count < grp->nr_sigs)
> +			idx = grp->sig_types[used_count];
> +	}
> +	return sig_type_names[idx];
> +}
> +
> +static ssize_t trigin_type_show(struct device *dev,
> +				struct device_attribute *attr,
> +				char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +	int sig_idx, used = 0, b_sz = PAGE_SIZE;
> +	const char *name;
> +
> +	for (sig_idx = 0; sig_idx < con->con_in->nr_sigs; sig_idx++) {
> +		name = cti_sig_type_name(con, sig_idx, true);
> +		used += scnprintf(buf + used, b_sz - used, "%s ", name);
> +	}
> +	used += scnprintf(buf + used, b_sz - used, "\n");
> +	return used;
> +}
> +
> +static ssize_t trigout_type_show(struct device *dev,
> +				 struct device_attribute *attr,
> +				 char *buf)
> +{
> +	struct dev_ext_attribute *ext_attr =
> +		container_of(attr, struct dev_ext_attribute, attr);
> +	struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> +	int sig_idx, used = 0, b_sz = PAGE_SIZE;
> +	const char *name;
> +
> +	for (sig_idx = 0; sig_idx < con->con_out->nr_sigs; sig_idx++) {
> +		name = cti_sig_type_name(con, sig_idx, false);
> +		used += scnprintf(buf + used, b_sz - used, "%s ", name);
> +	}
> +	used += scnprintf(buf + used, b_sz - used, "\n");
> +	return used;
> +}
> +
> +/*
> + * Array of show function names declared above to allow selection
> + * for the connection attributes
> + */
> +static p_show_fn show_fns[CTI_CON_ATTR_MAX] = {
> +	con_name_show,
> +	trigin_sig_show,
> +	trigout_sig_show,
> +	trigin_type_show,
> +	trigout_type_show,
> +};
> +
> +static int cti_create_con_sysfs_attr(struct cti_trig_con *con,
> +				     enum cti_conn_attr_type attr_type,
> +				     int attr_idx)
> +{
> +	struct dev_ext_attribute *dev_ext_attr = 0;

super minor nit: You may use "eattr" instead.


> +	char *name = 0;
> +
> +	dev_ext_attr = kzalloc(sizeof(struct dev_ext_attribute), GFP_KERNEL);


Could we not use devm_* alloc helpers everywhere ?

> +	if (dev_ext_attr) {
> +		name = kstrdup(con_attr_names[attr_type], GFP_KERNEL);
> +		if (name) {
> +			/* fill out the underlying attribute struct */
> +			dev_ext_attr->attr.attr.name = name;
> +			dev_ext_attr->attr.attr.mode = 0444;
> +
> +			/* now the device_attribute struct */
> +			dev_ext_attr->attr.show = show_fns[attr_type];
> +		} else {
> +			kfree(dev_ext_attr);
> +			return -ENOMEM;
> +		}
> +	} else {
> +		return -ENOMEM;
> +	}
> +	dev_ext_attr->var = con;
> +	con->con_attrs[attr_idx] = &dev_ext_attr->attr.attr;
> +	return 0;
> +}
> +
> +static struct attribute_group *
> +cti_create_con_sysfs_group(struct cti_device *ctidev, int con_idx,
> +			   struct cti_trig_con *con)
> +{
> +	struct attribute_group *group = NULL;
> +
> +	group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
> +	if (!group)
> +		return NULL;
> +
> +	group->name = kasprintf(GFP_KERNEL, "triggers%d", con_idx);
> +	if (!group->name) {
> +		kfree(group);
> +		return NULL;
> +	}
> +
> +	ctidev->con_groups[con_idx + CORESIGHT_CTI_STATIC_GROUPS_MAX - 1]
> +		= group;

nit:
	con_idx +=  CORESIGHT_CTI_STATIC_GROUPS_MAX - 1;
	ctidev->con_groups[con_idx] = group;


> +	con->attr_group = group;
> +	return group;
> +}
> +
> +/* create a triggers connection group and the attributes for that group */
> +static int cti_create_con_attr_set(int con_idx, struct cti_device *ctidev,
> +				   struct cti_trig_con *con)
> +{
> +	struct attribute_group *attr_group = NULL;
> +	int attr_idx = 0;
> +	int err = -ENOMEM;
> +
> +	attr_group = cti_create_con_sysfs_group(ctidev, con_idx, con);
> +	if (!attr_group)
> +		return -ENOMEM;
> +
> +	/* allocate NULL terminated array of attributes */
> +	con->con_attrs = kcalloc(CTI_CON_ATTR_MAX + 1,
> +				 sizeof(struct attribute *),
> +				 GFP_KERNEL);

Again why not devm_* allocations ? That takes the pain of freeing the
memory away and helps prevent memory leaks.

> +	if (!con->con_attrs)
> +		return -ENOMEM;
> +
> +	err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_NAME, attr_idx++);
> +	if (err)
> +		return err;
> +
> +	if (con->con_in->nr_sigs > 0) {
> +		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_SIG,
> +						attr_idx++);
> +		if (err)
> +			return err;
> +
> +		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_TYPES,
> +						attr_idx++);
> +		if (err)
> +			return err;
> +	}
> +
> +	if (con->con_in->nr_sigs > 0) {
> +		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_SIG,
> +						attr_idx++);
> +		if (err)
> +			return err;
> +
> +		err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_TYPES,
> +						attr_idx++);
> +		if (err)
> +			return err;
> +	}
> +	attr_group->attrs = con->con_attrs;
> +	return 0;
> +}
> +
> +/* create the array of group pointers for the CTI sysfs groups */
> +int cti_create_cons_groups(struct cti_device *ctidev)
> +{
> +	int i, nr_groups;
> +
> +	/* nr groups - dynamic + static + NULL terminator */
> +	nr_groups = ctidev->nr_trig_con + CORESIGHT_CTI_STATIC_GROUPS_MAX;
> +	ctidev->con_groups = kcalloc(nr_groups,
> +				     sizeof(struct attribute_group *),
> +				     GFP_KERNEL);
> +	if (!ctidev->con_groups)
> +		return -ENOMEM;
> +
> +	/* populate first locations with the static set of groups */
> +	for (i = 0; i < (CORESIGHT_CTI_STATIC_GROUPS_MAX - 1); i++)
> +		ctidev->con_groups[i] = coresight_cti_groups[i];
> +
> +	return 0;
> +}
> +

To be frank, it doesn't make sense to have this split of populating
the groups.

> +int cti_create_cons_sysfs(struct cti_drvdata *drvdata)
> +{
> +	struct cti_device *ctidev = &drvdata->ctidev;
> +	int err, con_idx = 0;
> +	struct cti_trig_con *tc = NULL;
> +
> +	err = cti_create_cons_groups(ctidev);
> +	if (err)
> +		return err;
> +
> +	/* add dynamic set for each connection */
> +	list_for_each_entry(tc, &ctidev->trig_cons, node) {
> +		err = cti_create_con_attr_set(con_idx++, ctidev, tc);
> +		if (err)
> +			goto cons_sysfs_err;
> +	}
> +	return 0;
> +
> +cons_sysfs_err:
> +	cti_destroy_cons_sysfs(ctidev);
> +	return err;
> +}
> +
> +void cti_free_con_attr(struct attribute *con_attr)
> +{
> +	struct device_attribute *dattr =
> +		container_of(con_attr, struct device_attribute, attr);
> +	struct dev_ext_attribute *dev_ext_attr =
> +		container_of(dattr, struct dev_ext_attribute, attr);
> +	kfree(con_attr->name);
> +	kfree(dev_ext_attr);
> +}
> +
> +void cti_free_con_group(struct attribute_group *attr_group)
> +{
> +	if (attr_group) {
> +		kfree(attr_group->name);
> +		kfree(attr_group);
> +	}
> +}
> +
> +void cti_destroy_cons_attr_set(int con_idx, struct cti_device *ctidev,
> +			       struct cti_trig_con *con)
> +{
> +	int i;
> +
> +	if (con->con_attrs) {
> +		for (i = 0; i < CTI_CON_ATTR_MAX; i++) {
> +			if (con->con_attrs[i])
> +				cti_free_con_attr(con->con_attrs[i]);
> +		}
> +		kfree(con->con_attrs);
> +	}
> +	cti_free_con_group(con->attr_group);
> +}
> +
> +void cti_destroy_cons_sysfs(struct cti_device *ctidev)
> +{
> +	struct cti_trig_con *tc;

minor nit: Please keep the variable name consistent if possible, helps a
lot with the code following. i.e, tc vs con above in 
cti_destroy_cons_attr_set().

> +	int con_idx = 0;
> +
> +	list_for_each_entry(tc, &ctidev->trig_cons, node) {
> +		cti_destroy_cons_attr_set(con_idx++, ctidev, tc);
> +	}
> +	kfree(ctidev->con_groups);
> +}
> +
> +/* attribute and group sysfs tables. */
>   static const struct attribute_group coresight_cti_group = {
>   	.attrs = coresight_cti_attrs,
>   };
> @@ -838,7 +1209,8 @@ static const struct attribute_group coresight_cti_channels_group = {
>   	.name = "channels",
>   };
>   
> -const struct attribute_group *coresight_cti_groups[] = {
> +const struct attribute_group *
> +coresight_cti_groups[CORESIGHT_CTI_STATIC_GROUPS_MAX] = {
>   	&coresight_cti_group,
>   	&coresight_cti_mgmt_group,
>   	&coresight_cti_regs_group,
> diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> index cf116463149a..c3d63cc53bdd 100644
> --- a/drivers/hwtracing/coresight/coresight-cti.c
> +++ b/drivers/hwtracing/coresight/coresight-cti.c
> @@ -561,6 +561,9 @@ static void cti_device_release(struct device *dev)
>   
>   	mutex_lock(&ect_mutex);
>   
> +	/* clear the dynamic sysfs associate with connections */
> +	cti_destroy_cons_sysfs(&drvdata->ctidev);
> +
>   	/* remove from the list */
>   	list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
>   		if (ect_item == drvdata) {
> @@ -636,12 +639,20 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
>   		goto err_out;
>   	}
>   
> +	/* create dynamic attributes for connections */
> +	ret = cti_create_cons_sysfs(drvdata);
> +	if (ret) {
> +		pr_err("%s: create dynamic sysfs entries failed\n",
> +		       cti_desc.name);

nit: It may be a good idea to include the actual device name (rather 
than just cti_xxx). so may be :

  dev_err(dev, "%s:....", cti_desc.name) ?


> +		goto err_out;
> +	}


Except for the devm_ alloc question, rest are fine.

Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 13/14] docs: coresight: Update documentation for CoreSight to cover CTI.
  2019-11-19 23:19 ` [PATCH v5 13/14] docs: coresight: Update documentation for CoreSight to cover CTI Mike Leach
  2019-11-27 19:00   ` Mathieu Poirier
@ 2019-12-02 10:43   ` Suzuki Kuruppassery Poulose
  2019-12-06 17:39     ` Mike Leach
  1 sibling, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-12-02 10:43 UTC (permalink / raw)
  To: Mike Leach, coresight, linux-arm-kernel, devicetree, linux-doc
  Cc: mathieu.poirier

On 19/11/2019 23:19, Mike Leach wrote:
> Add new document covering CTI / CTM usage in CoreSight.
> 
> Add section in coresight.rst introducing CTI and CTM modules with link
> to new document.
> 
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
>   .../trace/coresight/coresight-ect.rst         | 200 ++++++++++++++++++
>   Documentation/trace/coresight/coresight.rst   |  13 ++
>   2 files changed, 213 insertions(+)
>   create mode 100644 Documentation/trace/coresight/coresight-ect.rst
> 
> diff --git a/Documentation/trace/coresight/coresight-ect.rst b/Documentation/trace/coresight/coresight-ect.rst
> new file mode 100644
> index 000000000000..6448cf910f20
> --- /dev/null
> +++ b/Documentation/trace/coresight/coresight-ect.rst
> @@ -0,0 +1,200 @@
> +=============================================
> +CoreSight Embedded Cross Trigger (CTI & CTM).
> +=============================================
> +
> +    :Author:   Mike Leach <mike.leach@linaro.org>
> +    :Date:     November 2019
> +

...


> +
> +Channels API Directory
> +~~~~~~~~~~~~~~~~~~~~~~
> +
> +This provides an easy way to attach triggers to channels, without needing
> +the multiple register operations that are required if manipluating the
> +'regs' sub-dir elements directly.
> +
> +A number of files provide this API::
> +
> +   >$ ls ./cti_sys0/channels/
> +   chan_clear         chan_inuse         chan_xtrigs_view      trigin_detach
> +   chan_free          chan_pulse         chan_xtrigs_view_sel  trigout_attach
> +   chan_gate_disable  chan_set           trig_filter_enable    trigout_detach
> +   chan_gate_enable   chan_xtrigs_reset  trigin_attach         trigout_filtered
> +
> +Most access to these elements take the form::
> +
> +  echo <chan> [<trigger>] > /<device_path>/<operation>
> +
> +where the optional <trigger> is only needed for trigXX_attach | detach
> +operations.
> +
> +e.g.::
> +
> +   >$ echo 0 1 > ./cti_sys0/channels/trigout_attach
> +   >$ echo 0 > ./cti_sys0/channels/chan_set
> +
> +Attaches trigout(1) to channel(0), then activates channel(0) generating a
> +set state on cti_sys0.trigout(1)
> +
> +
> +*API operations*
> +
> +   * ``trigin_attach, trigout_attach``: Attach a channel to a trigger signal.
> +   * ``trigin_detach, trigout_detach``: Detach a channel from a trigger signal.
> +   * ``chan_set``: Set the channel - the set state will be propogated around
> +     the CTM to other connected devices.
> +   * ``chan_clear``: Clear the channel.
> +   * ``chan_pulse``: Set the channel for a single CoreSight clock cycle.
> +   * ``chan_gate_enable``: Write operation sets the CTI gate to propagate
> +     (enable) the channel to other devices. This operation takes a channel
> +     number. CTI gate is enabled for all channels by default at power up. Read
> +     to list the currently enabled channels on the gate.
> +   * ``chan_gate_disable``: Write channel number to disable gate for that
> +     channel.
> +   * ``chan_inuse``: Show the current channels attached to any signal
> +   * ``chan_free``: Show channels with no attached signals.
> +   * ``chan_xtrig_view``: write a channel number to select a channel to view,
> +     read to show the cross triggers programmed for the selected channel.
> +   * ``trig_filter_enable``: Defaults to enabled, disable to allow potentially
> +     dangerous output signals to be set.
> +   * ``trigout_filtered``: Trigger out signals that are prevented from being
> +     set if filtering ``trig_filter_enable`` is enabled. One use is to prevent
> +     accidental ``EDBGREQ`` signals stopping a core.
> +   * ``chan_xtrigs_reset``: Write 1 to clear all channel / trigger programming.
> +     Resets device hardware to default state.
> +
> +e.g.::
> +
> +   .../cti_sys0/channels# echo 2 1 > trigin_attach
> +   .../cti_sys0/channels# echo 2 6 > trigout_attach

minor nit: It may be a good idea to add a comment to describe what you
are doing with the above operations, to avoid looking up and mapping it
for someone looking it up. I am not too keen, but it is definitely
helpful.

> +   .../cti_sys0/channels# cat chan_free
> +   0-1,3
> +   .../cti_sys0/channels# cat chan_inuse
> +   2
> +   .../cti_sys0/channels# echo 2 > chan_xtrigs_view
> +   .../cti_sys0/channels# cat chan_xtrigs_view
> +   [2] IN: 1 OUT: 6
> +   .../cti_sys0/# echo 1 > enable
> +   .../cti_sys0/channels# echo 2 > chan_set
> +   .../cti_sys0/channels# cat ../regs/choutstatus
> +   0x4
> +   .../cti_sys0/channels# cat ../regs/trigoutstatus
> +   0x40
> +   .../cti_sys0/channels# echo 2 > chan_clear

> +   .../cti_sys0/channels# cat ../regs/trigoutstatus
> +   0x0
> +   .../cti_sys0/channels# cat ../regs/trigoutstatus
> +   0x0

nit: duplicate lines ?

Otherwise:

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI
  2019-11-29 11:33   ` Suzuki Kuruppassery Poulose
@ 2019-12-03 10:59     ` Mike Leach
  2019-12-03 11:28       ` Suzuki Kuruppassery Poulose
  0 siblings, 1 reply; 62+ messages in thread
From: Mike Leach @ 2019-12-03 10:59 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi Suzuki,

On Fri, 29 Nov 2019 at 11:33, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > The v8 architecture defines the relationship between a PE, its optional ETM
> > and a CTI. Unlike non-architectural CTIs which are implementation defined,
> > this has a fixed set of connections which can therefore be represented as a
> > simple tag in the device tree.
> >
> > This patch defines the tags needed to create an entry for this PE/ETM/CTI
> > relationship, and provides functionality to implement the connection model
> > in the CTI driver.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >   .../coresight/coresight-cti-platform.c        | 205 ++++++++++++++++++
> >   1 file changed, 205 insertions(+)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
> > index 665be86c585d..790dd30b85f5 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti-platform.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
> > @@ -3,10 +3,208 @@
> >    * Copyright (c) 2019, The Linaro Limited. All rights reserved.
> >    */
> >
> > +#include <dt-bindings/arm/coresight-cti-dt.h>
> >   #include <linux/of.h>
> >
> >   #include "coresight-cti.h"
> >
> > +/* Number of CTI signals in the v8 architecturally defined connection */
> > +#define NR_V8PE_IN_SIGS              2
> > +#define NR_V8PE_OUT_SIGS     3
> > +#define NR_V8ETM_INOUT_SIGS  4
> > +
> > +/* CTI device tree connection property keywords */
> > +#define CTI_DT_V8ARCH                "arm,cti-v8-arch"
> > +#define CTI_DT_CSDEV_ASSOC   "arm,cs-dev-assoc"
> > +
> > +/*
> > + * Find a registered coresight device from a device fwnode.
> > + * The node info is associated with the AMBA parent, but the
> > + * csdev keeps a copy so iterate round the coresight bus to
> > + * find the device.
> > + */
> > +static struct coresight_device *
> > +cti_get_assoc_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
>
> To be frank this has nothing to do with the CTI and is in a way
> a good candidate for a CoreSight generic function. We do similar
> stuff in coresight_fixup_device_conns(). So this could be :
>
> struct coresight_device *
> coresight_find_device_by_fwnode(const struct fwnode_handle *fwnode)
>
> > +{
> > +     struct device *dev;
> > +     struct coresight_device *csdev = NULL;
> > +
> > +     dev = bus_find_device_by_fwnode(&coresight_bustype, r_fwnode);
> > +     if (dev) {
> > +             csdev = to_coresight_device(dev);
> > +             put_device(dev);
> > +     }
> > +     return csdev;
> > +}
> > +
>
> And used in coresight_fixup_conns().
>

OK - I'll look at that.

> > +#ifdef CONFIG_OF
> > +/*
> > + * CTI can be bound to a CPU, or a system device.
> > + * CPU can be declared at the device top level or in a connections node
> > + * so need to check relative to node not device.
> > + */
> > +static int of_cti_get_cpu_at_node(const struct device_node *node)
> > +{
> > +     int cpu;
> > +     struct device_node *dn;
> > +
> > +     if (node == NULL)
> > +             return -1;
> > +
> > +     dn = of_parse_phandle(node, "cpu", 0);
> > +     /* CTI affinity defaults to no cpu */
> > +     if (!dn)
> > +             return -1;
> > +     cpu = of_cpu_node_to_id(dn);
> > +     of_node_put(dn);
> > +
> > +     /* No Affinity  if no cpu nodes are found */
> > +     return (cpu < 0) ? -1 : cpu;
> > +}
> > +
> > +static const char *of_cti_get_node_name(const struct device_node *node)
> > +{
> > +     if (node)
> > +             return node->full_name;
> > +     return "unknown";
> > +}
> > +#else
> > +static int of_cti_get_cpu_at_node(const struct device_node *node)
> > +{
> > +     return -1;
> > +}
> > +
> > +static const char *of_cti_get_node_name(const struct device_node *node)
> > +{
> > +     return "unknown";
> > +}
> > +#endif
> > +
> > +static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
> > +{
>
> You may simply reuse coresight_get_cpu() below, instead of adding this
> duplicate set of functions. See below.
>
>

No we can't. coresight_get_cpu gets the 'cpu' entry relative to the
device node, this gets the 'cpu' relative to the supplied node.
This is very important for the case where a none v8 architected PE is
attached to a CTI. This will use the devicetree form:-

cti@<addr> {
    [ some stuff  ]
   trig_conns@1 {
          cpu = <&CPU0>
          [trigger signal  connection info for this cpu]
   }
}

trig_conns is a child node and we must look for 'cpu' relative to it.


> > +static int cti_plat_create_v8_etm_connection(struct device *dev,
> > +                                          struct cti_drvdata *drvdata)
> > +{
> > +     int ret = -ENOMEM, i;
> > +     struct fwnode_handle *root_fwnode, *cs_fwnode;
> > +     const char *assoc_name = NULL;
> > +     struct coresight_device *csdev;
> > +     struct cti_trig_con *tc = NULL;
> > +
> > +     root_fwnode = dev_fwnode(dev);
> > +     if (IS_ERR_OR_NULL(root_fwnode))
> > +             return -EINVAL;
> > +
> > +     /* Can optionally have an etm node - return if not  */
> > +     cs_fwnode = fwnode_find_reference(root_fwnode, CTI_DT_CSDEV_ASSOC, 0);
> > +     if (IS_ERR_OR_NULL(cs_fwnode))
> > +             return 0;
> > +
> > +     /* allocate memory */
> > +     tc = cti_allocate_trig_con(dev, NR_V8ETM_INOUT_SIGS,
> > +                                NR_V8ETM_INOUT_SIGS);
> > +     if (!tc)
> > +             goto create_v8_etm_out;
> > +
> > +     /* build connection data */
> > +     tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */
> > +     tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */
> > +
> > +     /*
> > +      * The EXTOUT type signals from the ETM are connected to a set of input
> > +      * triggers on the CTI, the EXTIN being connected to output triggers.
> > +      */
> > +     for (i = 0; i < NR_V8ETM_INOUT_SIGS; i++) {
> > +             tc->con_in->sig_types[i] = ETM_EXTOUT;
> > +             tc->con_out->sig_types[i] = ETM_EXTIN;
> > +     }
> > +
> > +     /*
> > +      * We look to see if the ETM coresight device associated with this
> > +      * handle has been registered with the system - i.e. probed before
> > +      * this CTI. If so csdev will be non NULL and we can use the device
> > +      * name and pass the csdev to the connection entry function where
> > +      * the association will be recorded.
> > +      * If not, then simply record the name in the connection data, the
> > +      * probing of the ETM will call into the CTI driver API to update the
> > +      * association then.
> > +      */
> > +     csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
> > +     if (csdev)
> > +             assoc_name = dev_name(&csdev->dev);
>
> Does it make sense to defer the probing until the ETM device  turn up ?
> Its fine either way.
>

Not really as the ETM is optional but the PE still has a CTI.

> > +     else
> > +             assoc_name = cti_plat_get_node_name(cs_fwnode);
> > +     ret = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name);
> > +
> > +create_v8_etm_out:
> > +     fwnode_handle_put(cs_fwnode);
> > +     return ret;
> > +}
> > +
> > +/*
> > + * Create an architecturally defined v8 connection
> > + * must have a cpu, can have an ETM.
> > + */
> > +static int cti_plat_create_v8_connections(struct device *dev,
> > +                                       struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_device *cti_dev = &drvdata->ctidev;
> > +     struct cti_trig_con *tc = NULL;
> > +     int cpuid = 0;
> > +     char cpu_name_str[16];
> > +     int ret = -ENOMEM;
> > +
> > +     /* Must have a cpu node */
> > +     cpuid = cti_plat_get_cpu_at_node(dev_fwnode(dev));
>
> Could we reuse coresight_get_cpu(dev) instead ? I understand that the
> ACPI bindings have not been defined and it may be slightly different
> from what we have now for the ETMs (i.e, ETM node as child of the CPU
> node). But I don't see why we can't force it for the CTIs either.
> In the worst case, you could still reuse the of_coresgith_get_cpu(dev)
> instead of writing your own for the OF case.
>

See comments above - in theory here we could use coresight_get_cpu(),
but for consistency it is better to use that same function throughout
in case someone decided to "fix" it later.
I probably need to beef up the comments around
cti_plat_get_cpu_at_node / of_cti_get_cpu_at_node.

>
> > +     if (cpuid < 0) {
> > +             dev_warn(dev, "CTI v8 DT binding no cpu\n");
>
> This may be better off without mentioning the DT. e.g,
>
> "CTI Arm v8 architected connection: missing CPU\n"
>
OK
>
> > +             return -EINVAL;
> > +     }
> > +     cti_dev->cpu = cpuid;
> > +
> > +     /* Allocate the v8 cpu connection memory */
> > +     tc = cti_allocate_trig_con(dev, NR_V8PE_IN_SIGS, NR_V8PE_OUT_SIGS);
> > +     if (!tc)
> > +             goto of_create_v8_out;
> > +
> > +     /* Set the v8 PE CTI connection data */
> > +     tc->con_in->used_mask = 0x3; /* sigs <0 1> */
> > +     tc->con_in->sig_types[0] = PE_DBGTRIGGER;
> > +     tc->con_in->sig_types[1] = PE_PMUIRQ;
> > +     tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */
> > +     tc->con_out->sig_types[0] = PE_EDBGREQ;
> > +     tc->con_out->sig_types[1] = PE_DBGRESTART;
> > +     tc->con_out->sig_types[2] = PE_CTIIRQ;
> > +     scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid);
> > +
> > +     ret = cti_add_connection_entry(dev, drvdata, tc, NULL, cpu_name_str);
> > +     if (ret)
> > +             goto of_create_v8_out;
> > +
> > +     /* Create the v8 ETM associated connection */
> > +     ret = cti_plat_create_v8_etm_connection(dev, drvdata);
> > +     if (ret)
> > +             goto of_create_v8_out;
> > +
> > +     /* filter pe_edbgreq - PE trigout sig <0> */
> > +     drvdata->config.trig_out_filter |= 0x1;
> > +
> > +of_create_v8_out:
> > +     return ret;
> > +}
> > +
> >   /* get the hardware configuration & connection data. */
> >   int cti_plat_get_hw_data(struct device *dev,
> >                        struct cti_drvdata *drvdata)
> > @@ -14,6 +212,13 @@ int cti_plat_get_hw_data(struct device *dev,
> >       int rc = 0;
> >       struct cti_device *cti_dev = &drvdata->ctidev;
> >
> > +     /* check for a v8 architectural CTI device */
> minor nit: Check for Arm v8 architected CTI connection ?
>
> > +     if (device_property_read_bool(dev, CTI_DT_V8ARCH)) {
> > +             rc = cti_plat_create_v8_connections(dev, drvdata);
> > +             if (rc)
> > +                     return rc;
> > +     }
> > +
> >       /* if no connections, just add a single default based on max IN-OUT */
> >       if (cti_dev->nr_trig_con == 0)
> >               rc = cti_add_default_connection(dev, drvdata);
> >
>
>
> Suzuki

Thanks


Mike

--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI
  2019-12-03 10:59     ` Mike Leach
@ 2019-12-03 11:28       ` Suzuki Kuruppassery Poulose
  2019-12-03 12:25         ` Mike Leach
  0 siblings, 1 reply; 62+ messages in thread
From: Suzuki Kuruppassery Poulose @ 2019-12-03 11:28 UTC (permalink / raw)
  To: Mike Leach
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

On 03/12/2019 10:59, Mike Leach wrote:
> Hi Suzuki,
> 
> On Fri, 29 Nov 2019 at 11:33, Suzuki Kuruppassery Poulose
> <suzuki.poulose@arm.com> wrote:
>>
>> On 19/11/2019 23:19, Mike Leach wrote:
>>> The v8 architecture defines the relationship between a PE, its optional ETM
>>> and a CTI. Unlike non-architectural CTIs which are implementation defined,
>>> this has a fixed set of connections which can therefore be represented as a
>>> simple tag in the device tree.
>>>
>>> This patch defines the tags needed to create an entry for this PE/ETM/CTI
>>> relationship, and provides functionality to implement the connection model
>>> in the CTI driver.
>>>
>>> Signed-off-by: Mike Leach <mike.leach@linaro.org>
>>> ---


>>> +#ifdef CONFIG_OF
>>> +/*
>>> + * CTI can be bound to a CPU, or a system device.
>>> + * CPU can be declared at the device top level or in a connections node
>>> + * so need to check relative to node not device.
>>> + */
>>> +static int of_cti_get_cpu_at_node(const struct device_node *node)
>>> +{
>>> +     int cpu;
>>> +     struct device_node *dn;
>>> +
>>> +     if (node == NULL)
>>> +             return -1;
>>> +
>>> +     dn = of_parse_phandle(node, "cpu", 0);
>>> +     /* CTI affinity defaults to no cpu */
>>> +     if (!dn)
>>> +             return -1;
>>> +     cpu = of_cpu_node_to_id(dn);
>>> +     of_node_put(dn);
>>> +
>>> +     /* No Affinity  if no cpu nodes are found */
>>> +     return (cpu < 0) ? -1 : cpu;
>>> +}
>>> +
>>> +static const char *of_cti_get_node_name(const struct device_node *node)
>>> +{
>>> +     if (node)
>>> +             return node->full_name;
>>> +     return "unknown";
>>> +}
>>> +#else
>>> +static int of_cti_get_cpu_at_node(const struct device_node *node)
>>> +{
>>> +     return -1;
>>> +}
>>> +
>>> +static const char *of_cti_get_node_name(const struct device_node *node)
>>> +{
>>> +     return "unknown";
>>> +}
>>> +#endif
>>> +
>>> +static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
>>> +{
>>
>> You may simply reuse coresight_get_cpu() below, instead of adding this
>> duplicate set of functions. See below.
>>
>>
> 
> No we can't. coresight_get_cpu gets the 'cpu' entry relative to the
> device node, this gets the 'cpu' relative to the supplied node.
> This is very important for the case where a none v8 architected PE is
> attached to a CTI. This will use the devicetree form:-
> 
> cti@<addr> {
>      [ some stuff  ]
>     trig_conns@1 {
>            cpu = <&CPU0>
>            [trigger signal  connection info for this cpu]
>     }
> }
> 
> trig_conns is a child node and we must look for 'cpu' relative to it.

Ok. May be we could refactor the function to find the 'CPU' node
relative to the given "fwnode" and let the coresight_get_cpu() use it ?

int coresight_get_cpu(struct device *dev)
{
	return coresight_get_fwnode_cpu(dev_fwnode(dev));
}

That way it is clear what we are dealing with. i.e, fwnode of any level
(device or an intermediate node).

>>> +     csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
>>> +     if (csdev)
>>> +             assoc_name = dev_name(&csdev->dev);
>>
>> Does it make sense to defer the probing until the ETM device  turn up ?
>> Its fine either way.
>>
> 
> Not really as the ETM is optional but the PE still has a CTI.

Ah, you're right. Please ignore my comment.

Kind regards
Suzuki

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI
  2019-12-03 11:28       ` Suzuki Kuruppassery Poulose
@ 2019-12-03 12:25         ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-12-03 12:25 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi Suzuki,

On Tue, 3 Dec 2019 at 11:28, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 03/12/2019 10:59, Mike Leach wrote:
> > Hi Suzuki,
> >
> > On Fri, 29 Nov 2019 at 11:33, Suzuki Kuruppassery Poulose
> > <suzuki.poulose@arm.com> wrote:
> >>
> >> On 19/11/2019 23:19, Mike Leach wrote:
> >>> The v8 architecture defines the relationship between a PE, its optional ETM
> >>> and a CTI. Unlike non-architectural CTIs which are implementation defined,
> >>> this has a fixed set of connections which can therefore be represented as a
> >>> simple tag in the device tree.
> >>>
> >>> This patch defines the tags needed to create an entry for this PE/ETM/CTI
> >>> relationship, and provides functionality to implement the connection model
> >>> in the CTI driver.
> >>>
> >>> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> >>> ---
>
>
> >>> +#ifdef CONFIG_OF
> >>> +/*
> >>> + * CTI can be bound to a CPU, or a system device.
> >>> + * CPU can be declared at the device top level or in a connections node
> >>> + * so need to check relative to node not device.
> >>> + */
> >>> +static int of_cti_get_cpu_at_node(const struct device_node *node)
> >>> +{
> >>> +     int cpu;
> >>> +     struct device_node *dn;
> >>> +
> >>> +     if (node == NULL)
> >>> +             return -1;
> >>> +
> >>> +     dn = of_parse_phandle(node, "cpu", 0);
> >>> +     /* CTI affinity defaults to no cpu */
> >>> +     if (!dn)
> >>> +             return -1;
> >>> +     cpu = of_cpu_node_to_id(dn);
> >>> +     of_node_put(dn);
> >>> +
> >>> +     /* No Affinity  if no cpu nodes are found */
> >>> +     return (cpu < 0) ? -1 : cpu;
> >>> +}
> >>> +
> >>> +static const char *of_cti_get_node_name(const struct device_node *node)
> >>> +{
> >>> +     if (node)
> >>> +             return node->full_name;
> >>> +     return "unknown";
> >>> +}
> >>> +#else
> >>> +static int of_cti_get_cpu_at_node(const struct device_node *node)
> >>> +{
> >>> +     return -1;
> >>> +}
> >>> +
> >>> +static const char *of_cti_get_node_name(const struct device_node *node)
> >>> +{
> >>> +     return "unknown";
> >>> +}
> >>> +#endif
> >>> +
> >>> +static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
> >>> +{
> >>
> >> You may simply reuse coresight_get_cpu() below, instead of adding this
> >> duplicate set of functions. See below.
> >>
> >>
> >
> > No we can't. coresight_get_cpu gets the 'cpu' entry relative to the
> > device node, this gets the 'cpu' relative to the supplied node.
> > This is very important for the case where a none v8 architected PE is
> > attached to a CTI. This will use the devicetree form:-
> >
> > cti@<addr> {
> >      [ some stuff  ]
> >     trig_conns@1 {
> >            cpu = <&CPU0>
> >            [trigger signal  connection info for this cpu]
> >     }
> > }
> >
> > trig_conns is a child node and we must look for 'cpu' relative to it.
>
> Ok. May be we could refactor the function to find the 'CPU' node
> relative to the given "fwnode" and let the coresight_get_cpu() use it ?
>
> int coresight_get_cpu(struct device *dev)
> {
>         return coresight_get_fwnode_cpu(dev_fwnode(dev));
> }
>
> That way it is clear what we are dealing with. i.e, fwnode of any level
> (device or an intermediate node).
>

At present the generic coresight_get_cpu() deals with both DT and ACPI
bindings.
To refactor this would require re-factoring both binding types - and
at present we have no definition for ACPI bindings for CTI and hence
no way of knowing how the embedded cpu node is going to be
represented.

I think we have to take just the DT binding as is for now as a CTI
specific element and consider if it is worth re-factoring once the
ACPI bindings are defined

Regards

Mike

> >>> +     csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
> >>> +     if (csdev)
> >>> +             assoc_name = dev_name(&csdev->dev);
> >>
> >> Does it make sense to defer the probing until the ETM device  turn up ?
> >> Its fine either way.
> >>
> >
> > Not really as the ETM is optional but the PE still has a CTI.
>
> Ah, you're right. Please ignore my comment.
>
> Kind regards
> Suzuki



-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI.
  2019-11-29 14:18   ` Suzuki Kuruppassery Poulose
@ 2019-12-03 14:05     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-12-03 14:05 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi Suzuki,

On Fri, 29 Nov 2019 at 14:18, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > Adds support for CTIs whose connections are implementation defined at
> > hardware design time, and not constrained by v8 architecture.
> >
> > These CTIs have no standard connection setup, all the settings have to
> > be defined in the device tree files. The patch creates a set of connections
> > and trigger signals based on the information provided.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >   .../coresight/coresight-cti-platform.c        | 250 +++++++++++++++++-
> >   .../hwtracing/coresight/coresight-cti-sysfs.c |  11 +
> >   2 files changed, 257 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
> > index 790dd30b85f5..9c1ff432b487 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti-platform.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
> > @@ -13,9 +13,19 @@
> >   #define NR_V8PE_OUT_SIGS    3
> >   #define NR_V8ETM_INOUT_SIGS 4
> >
> > +/* CTI device tree trigger connection node keyword */
> > +#define CTI_DT_CONNS         "trig-conns"
> > +
> >   /* CTI device tree connection property keywords */
> >   #define CTI_DT_V8ARCH               "arm,cti-v8-arch"
> >   #define CTI_DT_CSDEV_ASSOC  "arm,cs-dev-assoc"
> > +#define CTI_DT_TRIGIN_SIGS   "arm,trig-in-sigs"
> > +#define CTI_DT_TRIGOUT_SIGS  "arm,trig-out-sigs"
> > +#define CTI_DT_TRIGIN_TYPES  "arm,trig-in-types"
> > +#define CTI_DT_TRIGOUT_TYPES "arm,trig-out-types"
> > +#define CTI_DT_FILTER_OUT_SIGS       "arm,trig-filters"
> > +#define CTI_DT_CONN_NAME     "arm,trig-conn-name"
> > +#define CTI_DT_CTM_ID                "arm,cti-ctm-id"
> >
> >   /*
> >    * Find a registered coresight device from a device fwnode.
> > @@ -68,6 +78,12 @@ static const char *of_cti_get_node_name(const struct device_node *node)
> >               return node->full_name;
> >       return "unknown";
> >   }
> > +
> > +static bool of_cti_node_name_eq(const struct device_node *node,
> > +                             const char *name)
> > +{
> > +     return of_node_name_eq(node, name);
> > +}
> >   #else
> >   static int of_cti_get_cpu_at_node(const struct device_node *node)
> >   {
> > @@ -78,6 +94,12 @@ static const char *of_cti_get_node_name(const struct device_node *node)
> >   {
> >       return "unknown";
> >   }
> > +
> > +static bool of_cti_node_name_eq(const struct device_node *node,
> > +                             const char *name)
> > +{
> > +     return false;
> > +}
> >   #endif
>
> nit: You don't need this wrapper of_node_name_eq() is already defined to
> return false for !CONFIG_OF.
>
>

OK.

> >
> >   static int cti_plat_get_cpu_at_node(struct fwnode_handle *fwnode)
> > @@ -94,6 +116,14 @@ static const char *cti_plat_get_node_name(struct fwnode_handle *fwnode)
> >       return "unknown";
> >   }
> >
> > +static bool cti_plat_node_name_eq(struct fwnode_handle *fwnode,
> > +                               const char *name)
> > +{
> > +     if (is_of_node(fwnode))
> > +             return of_cti_node_name_eq(to_of_node(fwnode), name);
>
> As mentioned above you could simply use of_node_name_eq() here.
>
> > +     return false;
> > +}
> > +
> >   static int cti_plat_create_v8_etm_connection(struct device *dev,
> >                                            struct cti_drvdata *drvdata)
> >   {
> > @@ -205,6 +235,214 @@ static int cti_plat_create_v8_connections(struct device *dev,
> >       return ret;
> >   }
> >
> > +static int cti_plat_count_sig_elements(const struct fwnode_handle *fwnode,
> > +                                    const char *name)
> > +{
> > +     int nr_elem = fwnode_property_count_u32(fwnode, name);
> > +
> > +     return (nr_elem < 0 ? 0 : nr_elem);
> > +}
> > +
> > +static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp,
> > +                                 const struct fwnode_handle *fwnode,
> > +                                 const char *grp_name)
> > +{
> > +     int idx, err = 0;
> > +     u32 *values;
> > +
> > +     if (!tgrp->nr_sigs)
> > +             return 0;
> > +
> > +     values = kcalloc(tgrp->nr_sigs, sizeof(u32), GFP_KERNEL);
> > +     if (!values)
> > +             return -ENOMEM;
> > +
> > +     err = fwnode_property_read_u32_array(fwnode, grp_name,
> > +                                          values, tgrp->nr_sigs);
> > +
> > +     if (!err) {
> > +             /* set the signal usage mask */
> > +             for (idx = 0; idx < tgrp->nr_sigs; idx++)
> > +                     tgrp->used_mask |= BIT(values[idx]);
> > +     }
> > +
> > +     kfree(values);
> > +     return err;
> > +}
> > +
> > +static int cti_plat_read_trig_types(struct cti_trig_grp *tgrp,
> > +                                 const struct fwnode_handle *fwnode,
> > +                                 const char *type_name)
> > +{
> > +     int items, used = 0, err = 0, nr_sigs;
> > +     u32 *values = NULL, i;
> > +
> > +     /* allocate an array according to number of signals in connection */
> > +     nr_sigs = tgrp->nr_sigs;
> > +     if (!nr_sigs)
> > +             return 0;
> > +
> > +     /* see if any types have been included in the device description */
> > +     items = cti_plat_count_sig_elements(fwnode, type_name);
> > +     if (items > nr_sigs)
> > +             return -EINVAL;
> > +
> > +     /* need an array to store the values iff there are any */
> > +     if (items) {
> > +             values = kcalloc(items, sizeof(u32), GFP_KERNEL);
> > +             if (!values)
> > +                     return -ENOMEM;
> > +
> > +             err = fwnode_property_read_u32_array(fwnode, type_name,
> > +                                                  values, items);
> > +             if (err)
> > +                     goto read_trig_types_out;
> > +     }
> > +
> > +     /*
> > +      * Match type id to signal index, 1st type to 1st index etc.
> > +      * If fewer types than signals default remainder to GEN_IO.
> > +      */
> > +     for (i = 0; i < nr_sigs; i++) {
> > +             if (used < items) {
> > +                     tgrp->sig_types[i] =
> > +                             values[i] < CTI_TRIG_MAX ? values[i] : GEN_IO;
> > +                     used++;
>
> Do we really need "used" here ? Couldn't this be :
>
No we don't - I'll fix it.

>                 if (i < items) {
>
>                 }
>
> > +             } else {
>
>    +                    /* Mark the undefined connections as GEN_IO */ ?
>
> > +                     tgrp->sig_types[i] = GEN_IO;
> > +             }
> > +     }
>
> ...
>
> > +
> > +     /* read the connection name if set - may be overridden by later */
> > +     fwnode_property_read_string(fwnode, CTI_DT_CONN_NAME, &assoc_name);
> > +
> > +     /* associated cpu ? */
> > +     cpuid = cti_plat_get_cpu_at_node(fwnode);
> > +     if (cpuid >= 0) {
> > +             drvdata->ctidev.cpu = cpuid;
> > +             scnprintf(cpu_name_str, sizeof(cpu_name_str), "cpu%d", cpuid);
> > +             assoc_name = cpu_name_str;
> > +     } else {
> > +             /* associated device ? */
> > +             cs_fwnode = fwnode_find_reference(fwnode,
> > +                                               CTI_DT_CSDEV_ASSOC, 0);
>
> > +             if (!IS_ERR_OR_NULL(cs_fwnode)) {
>
> --- Cut - here --
> > +                     csdev = cti_get_assoc_csdev_by_fwnode(cs_fwnode);
> > +                     if (csdev) /* use device name if csdev found */
> > +                             assoc_name = dev_name(&csdev->dev);
> > +                     else  /* otherwise node name for later association */
> > +                             assoc_name = cti_plat_get_node_name(cs_fwnode);
>
> --- end - here --
>
> I believe we do this for arm_v8 architected connections too. May be make
> this a helper ?
>
OK

> > +                     fwnode_handle_put(cs_fwnode);
> > +             }
> > +     }
> > +     /* set up a connection */
> > +     err = cti_add_connection_entry(dev, drvdata, tc, csdev, assoc_name);
> > +
> > +create_con_err:
> > +     return err;
> > +}
> > +
> > +static int cti_plat_create_impdef_connections(struct device *dev,
> > +                                           struct cti_drvdata *drvdata)
> > +{
> > +     int rc = 0;
> > +     struct fwnode_handle *fwnode = dev_fwnode(dev);
> > +     struct fwnode_handle *child = NULL;
> > +
> > +     if (IS_ERR_OR_NULL(fwnode))
> > +             return -EINVAL;
> > +
> > +     fwnode_for_each_child_node(fwnode, child) {
> > +             if (cti_plat_node_name_eq(child, CTI_DT_CONNS))
> > +                     rc = cti_plat_create_connection(dev, drvdata, child);
> > +             if (rc != 0)
> > +                     break;
>
> minor nit: To make it more obvious :
>
>                 if (cti_plat_node_name_eq(child, CTI_DT_CONNS)) {
>                         rc = cti_plat_create_connection(dev, drvdata,
>                                                         child);
>                         if (rc)
>                                 break;
>                 }
>
> Suzuki

Thanks


Mike

--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 01/14] coresight: cti: Initial CoreSight CTI Driver
  2019-11-29 12:05     ` Mike Leach
@ 2019-12-03 16:53       ` Mathieu Poirier
  0 siblings, 0 replies; 62+ messages in thread
From: Mathieu Poirier @ 2019-12-03 16:53 UTC (permalink / raw)
  To: Mike Leach
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Suzuki K. Poulose

On Fri, 29 Nov 2019 at 05:05, Mike Leach <mike.leach@linaro.org> wrote:
>
> Hi Mathieu,
>
> On Thu, 21 Nov 2019 at 20:21, Mathieu Poirier
> <mathieu.poirier@linaro.org> wrote:
> >
> > On Tue, Nov 19, 2019 at 11:18:59PM +0000, Mike Leach wrote:
> > > This introduces a baseline CTI driver and associated configuration files.
> > >
> > > Uses the platform agnostic naming standard for CoreSight devices, along
> > > with a generic platform probing method that currently supports device
> > > tree descriptions, but allows for the ACPI bindings to be added once these
> > > have been defined for the CTI devices.
> > >
> > > Driver will probe for the device on the AMBA bus, and load the CTI driver
> > > on CoreSight ID match to CTI IDs in tables.
> > >
> > > Initial sysfs support for enable / disable provided.
> > >
> > > Default CTI interconnection data is generated based on hardware
> > > register signal counts, with no additional connection information.
> > >
> > > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > > ---
> > >  drivers/hwtracing/coresight/Kconfig           |  12 +
> > >  drivers/hwtracing/coresight/Makefile          |   3 +
> > >  .../coresight/coresight-cti-platform.c        |  53 +++
> > >  .../hwtracing/coresight/coresight-cti-sysfs.c |  72 +++
> > >  drivers/hwtracing/coresight/coresight-cti.c   | 448 ++++++++++++++++++
> > >  drivers/hwtracing/coresight/coresight-cti.h   | 186 ++++++++
> > >  drivers/hwtracing/coresight/coresight.c       |   3 +
> > >  include/linux/coresight.h                     |  23 +
> > >  8 files changed, 800 insertions(+)
> > >  create mode 100644 drivers/hwtracing/coresight/coresight-cti-platform.c
> > >  create mode 100644 drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > >  create mode 100644 drivers/hwtracing/coresight/coresight-cti.c
> > >  create mode 100644 drivers/hwtracing/coresight/coresight-cti.h
> > >
> > > diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> > > index 6ff30e25af55..45d3822c8c8c 100644
> > > --- a/drivers/hwtracing/coresight/Kconfig
> > > +++ b/drivers/hwtracing/coresight/Kconfig
> > > @@ -110,4 +110,16 @@ 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 (CTI) driver"
> > > +     depends on ARM || ARM64
> > > +     help
> > > +       This driver provides support for CoreSight CTI and CTM components.
> > > +       These provide hardware triggering events between CoreSight trace
> > > +       source and sink components. These can be used to halt trace or
> > > +       inject events into the trace stream. CTI also provides a software
> > > +       control to trigger the same halt events. This can provide fast trace
> > > +       halt compared to disabling sources and sinks normally in driver
> > > +       software.
> > > +
> > >  endif
> > > diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> > > index 3c0ac421e211..0e3e72f0f510 100644
> > > --- a/drivers/hwtracing/coresight/Makefile
> > > +++ b/drivers/hwtracing/coresight/Makefile
> > > @@ -17,3 +17,6 @@ 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 \
> > > +                             coresight-cti-platform.o \
> > > +                             coresight-cti-sysfs.o
> > > diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
> > > new file mode 100644
> > > index 000000000000..665be86c585d
> > > --- /dev/null
> > > +++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
> > > @@ -0,0 +1,53 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Copyright (c) 2019, The Linaro Limited. All rights reserved.
> > > + */
> > > +
> > > +#include <linux/of.h>
> > > +
> > > +#include "coresight-cti.h"
> > > +
> > > +/* get the hardware configuration & connection data. */
> > > +int cti_plat_get_hw_data(struct device *dev,
> > > +                      struct cti_drvdata *drvdata)
> > > +{
> > > +     int rc = 0;
> > > +     struct cti_device *cti_dev = &drvdata->ctidev;
> > > +
> > > +     /* if no connections, just add a single default based on max IN-OUT */
> > > +     if (cti_dev->nr_trig_con == 0)
> > > +             rc = cti_add_default_connection(dev, drvdata);
> > > +     return rc;
> > > +}
> > > +
> > > +struct coresight_platform_data *
> > > +coresight_cti_get_platform_data(struct device *dev)
> > > +{
> > > +     int ret = -ENOENT;
> > > +     struct coresight_platform_data *pdata = NULL;
> > > +     struct fwnode_handle *fwnode = dev_fwnode(dev);
> > > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev);
> > > +
> > > +     if (IS_ERR_OR_NULL(fwnode))
> > > +             goto error;
> > > +
> > > +     /*
> > > +      * Alloc platform data but leave it zero init. CTI does not use the
> > > +      * same connection infrastructuree as trace path components but an
> > > +      * empty struct enables us to use the standard coresight component
> > > +      * registration code.
> > > +      */
> > > +     pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
> > > +     if (!pdata) {
> > > +             ret = -ENOMEM;
> > > +             goto error;
> > > +     }
> > > +
> > > +     /* get some CTI specifics */
> > > +     ret = cti_plat_get_hw_data(dev, drvdata);
> > > +
> > > +     if (!ret)
> > > +             return pdata;
> > > +error:
> > > +     return ERR_PTR(ret);
> > > +}
> > > diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > > new file mode 100644
> > > index 000000000000..a832b8c6b866
> > > --- /dev/null
> > > +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > > @@ -0,0 +1,72 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Copyright (c) 2019 Linaro Limited, All rights reserved.
> > > + * Author: Mike Leach <mike.leach@linaro.org>
> > > + */
> > > +
> > > +#include <linux/coresight.h>
> > > +
> > > +#include "coresight-cti.h"
> > > +
> > > +/* basic attributes */
> > > +static ssize_t enable_show(struct device *dev,
> > > +                        struct device_attribute *attr,
> > > +                        char *buf)
> > > +{
> > > +     int enable_req;
> > > +     bool enabled, powered;
> > > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > > +     ssize_t size = 0;
> > > +
> > > +     enable_req = atomic_read(&drvdata->config.enable_req_count);
> > > +     spin_lock(&drvdata->spinlock);
> > > +     powered = drvdata->config.hw_powered;
> > > +     enabled = drvdata->config.hw_enabled;
> > > +     spin_unlock(&drvdata->spinlock);
> > > +
> > > +     if (powered) {
> > > +             size = scnprintf(buf, PAGE_SIZE, "cti %s; powered;\n",
> > > +                              enabled ? "enabled" : "disabled");
> > > +     } else {
> > > +             size = scnprintf(buf, PAGE_SIZE, "cti %s; unpowered;\n",
> > > +                              enable_req ? "enable req" : "disabled");
> > > +     }
> > > +     return size;
> > > +}
> > > +
> > > +static ssize_t enable_store(struct device *dev,
> > > +                         struct device_attribute *attr,
> > > +                         const char *buf, size_t size)
> > > +{
> > > +     int ret = 0;
> > > +     unsigned long val;
> > > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > > +
> > > +     ret = kstrtoul(buf, 0, &val);
> > > +     if (ret)
> > > +             return ret;
> > > +
> > > +     if (val)
> > > +             ret = cti_enable(drvdata->csdev);
> > > +     else
> > > +             ret = cti_disable(drvdata->csdev);
> > > +     if (ret)
> > > +             return ret;
> > > +     return size;
> > > +}
> > > +static DEVICE_ATTR_RW(enable);
> > > +
> > > +/* attribute and group sysfs tables. */
> > > +static struct attribute *coresight_cti_attrs[] = {
> > > +     &dev_attr_enable.attr,
> > > +     NULL,
> > > +};
> > > +
> > > +static const struct attribute_group coresight_cti_group = {
> > > +     .attrs = coresight_cti_attrs,
> > > +};
> > > +
> > > +const struct attribute_group *coresight_cti_groups[] = {
> > > +     &coresight_cti_group,
> > > +     NULL,
> > > +};
> > > diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> > > new file mode 100644
> > > index 000000000000..7ae48bf62d17
> > > --- /dev/null
> > > +++ b/drivers/hwtracing/coresight/coresight-cti.c
> > > @@ -0,0 +1,448 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Copyright (c) 2018 Linaro Limited, All rights reserved.
> > > + * Author: Mike Leach <mike.leach@linaro.org>
> > > + */
> > > +
> > > +#include "coresight-cti.h"
> > > +
> > > +/**
> > > + * CTI devices can be associated with a PE, or be connected to CoreSight
> > > + * hardware. We have a list of all CTIs irrespective of CPU bound or
> > > + * otherwise.
> > > + *
> > > + * We assume that the non-CPU CTIs are always powered as we do with sinks etc.
> > > + *
> > > + * We leave the client to figure out if all the CTIs are interconnected with
> > > + * the same CTM, in general this is the case but does not always have to be.
> > > + */
> > > +
> > > +/* net of CTI devices connected via CTM */
> > > +LIST_HEAD(ect_net);
> > > +
> > > +/* protect the list */
> > > +static DEFINE_MUTEX(ect_mutex);
> > > +
> > > +#define csdev_to_cti_drvdata(csdev)  \
> > > +     dev_get_drvdata(csdev->dev.parent)
> > > +
> > > +/*
> > > + * CTI naming. CTI bound to cores will have the name cti_cpu<N> where
> > > + * N is the CPU ID. System CTIs will have the name cti_sys<I> where I
> > > + * is an index allocated by order of discovery.
> > > + *
> > > + * CTI device name list - for CTI not bound to cores.
> > > + */
> > > +DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys");
> > > +
> > > +/* write set of regs to hardware - call with spinlock claimed */
> > > +void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
> > > +{
> > > +     struct cti_config *config = &drvdata->config;
> > > +     int i;
> > > +
> > > +     CS_UNLOCK(drvdata->base);
> > > +
> > > +     /* disable CTI before writing registers */
> > > +     writel_relaxed(0, drvdata->base + CTICONTROL);
> > > +
> > > +     /* write the CTI trigger registers */
> > > +     for (i = 0; i < config->nr_trig_max; i++) {
> > > +             writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i));
> > > +             writel_relaxed(config->ctiouten[i],
> > > +                            drvdata->base + CTIOUTEN(i));
> > > +     }
> > > +
> > > +     /* other regs */
> > > +     writel_relaxed(config->ctigate, drvdata->base + CTIGATE);
> > > +     writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
> > > +     writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);
> > > +
> > > +     /* re-enable CTI */
> > > +     writel_relaxed(1, drvdata->base + CTICONTROL);
> > > +
> > > +     CS_LOCK(drvdata->base);
> > > +}
> > > +
> > > +static void cti_enable_hw_smp_call(void *info)
> > > +{
> > > +     struct cti_drvdata *drvdata = info;
> > > +
> > > +     cti_write_all_hw_regs(drvdata);
> > > +}
> > > +
> > > +/* write regs to hardware and enable */
> > > +static int cti_enable_hw(struct cti_drvdata *drvdata)
> > > +{
> > > +     struct cti_config *config = &drvdata->config;
> > > +     struct device *dev = &drvdata->csdev->dev;
> > > +     int rc = 0;
> > > +
> > > +     pm_runtime_get_sync(dev->parent);
> > > +     spin_lock(&drvdata->spinlock);
> > > +
> > > +     /* no need to do anything if enabled or unpowered*/
> > > +     if (config->hw_enabled || !config->hw_powered)
> > > +             goto cti_state_unchanged;
> > > +
> > > +     /* claim the device */
> > > +     rc = coresight_claim_device(drvdata->base);
> > > +     if (rc)
> > > +             goto cti_err_not_enabled;
> > > +
> > > +     if (drvdata->ctidev.cpu >= 0) {
> > > +             rc = smp_call_function_single(drvdata->ctidev.cpu,
> > > +                                           cti_enable_hw_smp_call,
> > > +                                           drvdata, 1);
> > > +             if (rc)
> > > +                     goto cti_err_not_enabled;
> > > +     } else {
> > > +             cti_write_all_hw_regs(drvdata);
> > > +     }
> > > +
> > > +     config->hw_enabled = true;
> > > +     atomic_inc(&drvdata->config.enable_req_count);
> > > +     spin_unlock(&drvdata->spinlock);
> > > +     return rc;
> > > +
> > > +cti_state_unchanged:
> > > +     atomic_inc(&drvdata->config.enable_req_count);
> > > +
> > > +     /* cannot enable due to error */
> > > +cti_err_not_enabled:
> > > +     spin_unlock(&drvdata->spinlock);
> > > +     pm_runtime_put(dev->parent);
> > > +     return rc;
> > > +}
> > > +
> > > +/* disable hardware */
> > > +static int cti_disable_hw(struct cti_drvdata *drvdata)
> > > +{
> > > +     struct cti_config *config = &drvdata->config;
> > > +     struct device *dev = &drvdata->csdev->dev;
> > > +
> > > +     spin_lock(&drvdata->spinlock);
> > > +
> > > +     /* check refcount - disable on 0 */
> > > +     if (atomic_dec_return(&drvdata->config.enable_req_count) > 0)
> > > +             goto cti_not_disabled;
> > > +
> > > +     /* no need to do anything if disabled or cpu unpowered */
> > > +     if (!config->hw_enabled || !config->hw_powered)
> > > +             goto cti_not_disabled;
> > > +
> > > +     CS_UNLOCK(drvdata->base);
> > > +
> > > +     /* disable CTI */
> > > +     writel_relaxed(0, drvdata->base + CTICONTROL);
> > > +     config->hw_enabled = false;
> > > +
> > > +     coresight_disclaim_device_unlocked(drvdata->base);
> > > +     CS_LOCK(drvdata->base);
> > > +     spin_unlock(&drvdata->spinlock);
> > > +     pm_runtime_put(dev);
> > > +     return 0;
> > > +
> > > +     /* not disabled this call */
> > > +cti_not_disabled:
> > > +     spin_unlock(&drvdata->spinlock);
> > > +     return 0;
> > > +}
> > > +
> > > +/*
> > > + * Look at the HW DEVID register for some of the HW settings.
> > > + * DEVID[15:8] - max number of in / out triggers.
> > > + */
> > > +#define CTI_DEVID_MAXTRIGS(devid_val) (int)((devid_val & 0xFF00) >> 8)
> > > +
> > > +/* DEVID[19:16] - number of CTM channels */
> > > +#define CTI_DEVID_CTMCHANNELS(devid_val) (int)((devid_val & 0xF0000) >> 16)
> > > +
> > > +static void cti_set_default_config(struct device *dev,
> > > +                                struct cti_drvdata *drvdata)
> > > +{
> > > +     struct cti_config *config = &drvdata->config;
> > > +     u32 devid;
> > > +
> > > +     devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
> > > +     config->nr_trig_max = CTI_DEVID_MAXTRIGS(devid);
> > > +
> > > +     /*
> > > +      * no current hardware should exceed this, but protect the driver
> > > +      * in case of fault / out of spec hw
> > > +      */
> > > +     if (config->nr_trig_max > CTIINOUTEN_MAX) {
> > > +             dev_warn_once(dev,
> > > +                     "Limiting HW MaxTrig value(%d) to driver max(%d)\n",
> > > +                     config->nr_trig_max, CTIINOUTEN_MAX);
> > > +             config->nr_trig_max = CTIINOUTEN_MAX;
> > > +     }
> > > +
> > > +     config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid);
> > > +
> > > +     /* Most regs default to 0 as zalloc'ed except...*/
> > > +     config->trig_filter_enable = true;
> > > +     config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
> > > +     atomic_set(&config->enable_req_count, 0);
> > > +}
> > > +
> > > +/*
> > > + * Add a connection entry to the list of connections for this
> > > + * CTI device.
> > > + */
> > > +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
> > > +                          struct cti_trig_con *tc,
> > > +                          struct coresight_device *csdev,
> > > +                          const char *assoc_dev_name)
> > > +{
> > > +     struct cti_device *cti_dev = &drvdata->ctidev;
> > > +
> > > +     tc->con_dev = csdev;
> > > +     /*
> > > +      * Prefer actual associated CS device dev name to supplied value -
> > > +      * which is likely to be node name / other conn name.
> > > +      */
> > > +     if (csdev)
> > > +             tc->con_dev_name = devm_kstrdup(dev,
> > > +                                             dev_name(&csdev->dev),
> > > +                                             GFP_KERNEL);
> > > +     else if (assoc_dev_name != NULL)
> > > +             tc->con_dev_name = devm_kstrdup(dev,
> > > +                                             assoc_dev_name, GFP_KERNEL);
> > > +     list_add_tail(&tc->node, &cti_dev->trig_cons);
> > > +     cti_dev->nr_trig_con++;
> > > +
> > > +     /* add connection usage bit info to overall info */
> > > +     drvdata->config.trig_in_use |= tc->con_in->used_mask;
> > > +     drvdata->config.trig_out_use |= tc->con_out->used_mask;
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +/* create a trigger connection with appropriately sized signal groups */
> > > +struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
> > > +                                        int out_sigs)
> > > +{
> > > +     struct cti_trig_con *tc = NULL;
> > > +     struct cti_trig_grp *in = NULL, *out = NULL;
> > > +
> > > +     tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL);
> > > +     if (!tc)
> > > +             return tc;
> > > +
> > > +     in = devm_kzalloc(dev,
> > > +                       offsetof(struct cti_trig_grp, sig_types[in_sigs]),
> > > +                       GFP_KERNEL);
> > > +     if (!in)
> > > +             return NULL;
> > > +
> > > +     out = devm_kzalloc(dev,
> > > +                        offsetof(struct cti_trig_grp, sig_types[out_sigs]),
> > > +                        GFP_KERNEL);
> > > +     if (!out)
> > > +             return NULL;
> > > +
> > > +     tc->con_in = in;
> > > +     tc->con_out = out;
> > > +     tc->con_in->nr_sigs = in_sigs;
> > > +     tc->con_out->nr_sigs = out_sigs;
> > > +     return tc;
> > > +}
> > > +
> > > +/*
> > > + * Add a default connection if nothing else is specified.
> > > + * single connection based on max in/out info, no assoc device
> > > + */
> > > +int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
> > > +{
> > > +     int ret = 0;
> > > +     int n_trigs = drvdata->config.nr_trig_max;
> > > +     u32 n_trig_mask = GENMASK(n_trigs - 1, 0);
> > > +     struct cti_trig_con *tc = NULL;
> > > +
> > > +     /*
> > > +      * Assume max trigs for in and out,
> > > +      * all used, default sig types allocated
> > > +      */
> > > +     tc = cti_allocate_trig_con(dev, n_trigs, n_trigs);
> > > +     if (!tc)
> > > +             return -ENOMEM;
> > > +
> > > +     tc->con_in->used_mask = n_trig_mask;
> > > +     tc->con_out->used_mask = n_trig_mask;
> > > +     ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default");
> > > +     return ret;
> > > +}
> > > +
> > > +/** cti ect operations **/
> > > +int cti_enable(struct coresight_device *csdev)
> > > +{
> > > +     struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> > > +
> > > +     /* enable hardware with refcount */
> > > +     return cti_enable_hw(drvdata);
> > > +}
> > > +
> > > +int cti_disable(struct coresight_device *csdev)
> > > +{
> > > +     struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
> > > +
> > > +     /* disable hardware with refcount */
> > > +     return cti_disable_hw(drvdata);
> > > +}
> > > +
> > > +const struct coresight_ops_ect cti_ops_ect = {
> > > +     .enable = cti_enable,
> > > +     .disable = cti_disable,
> > > +};
> > > +
> > > +const struct coresight_ops cti_ops = {
> > > +     .ect_ops = &cti_ops_ect,
> > > +};
> > > +
> > > +/*
> > > + * Free up CTI specific resources
> > > + * called by dev->release, need to call down to underlying csdev release.
> > > + */
> > > +static void cti_device_release(struct device *dev)
> > > +{
> > > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > > +     struct cti_drvdata *ect_item, *ect_tmp;
> > > +
> > > +     mutex_lock(&ect_mutex);
> > > +
> > > +     /* remove from the list */
> > > +     list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
> > > +             if (ect_item == drvdata) {
> > > +                     list_del(&ect_item->node);
> > > +                     break;
> > > +             }
> > > +     }
> > > +     mutex_unlock(&ect_mutex);
> > > +
> > > +     if (drvdata->csdev_release)
> > > +             drvdata->csdev_release(dev);
> > > +}
> > > +
> > > +static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> > > +{
> > > +     int ret = 0;
> > > +     void __iomem *base;
> > > +     struct device *dev = &adev->dev;
> > > +     struct cti_drvdata *drvdata = NULL;
> > > +     struct coresight_desc cti_desc;
> > > +     struct coresight_platform_data *pdata = NULL;
> > > +     struct resource *res = &adev->res;
> > > +
> > > +     /* driver data*/
> > > +     drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
> > > +     if (!drvdata) {
> > > +             ret = -ENOMEM;
> > > +             dev_info(dev, "%s, mem err\n", __func__);
> > > +             goto err_out;
> > > +     }
> > > +
> > > +     /* Validity for the resource is already checked by the AMBA core */
> > > +     base = devm_ioremap_resource(dev, res);
> > > +     if (IS_ERR(base)) {
> > > +             ret = PTR_ERR(base);
> > > +             dev_info(dev, "%s, remap err\n", __func__);
> > > +             goto err_out;
> > > +     }
> > > +     drvdata->base = base;
> > > +
> > > +     dev_set_drvdata(dev, drvdata);
> > > +
> > > +     /* default CTI device info  */
> > > +     drvdata->ctidev.cpu = -1;
> > > +     drvdata->ctidev.nr_trig_con = 0;
> > > +     drvdata->ctidev.ctm_id = 0;
> > > +     INIT_LIST_HEAD(&drvdata->ctidev.trig_cons);
> > > +
> > > +     spin_lock_init(&drvdata->spinlock);
> > > +
> > > +     /* initialise CTI driver config values */
> > > +     cti_set_default_config(dev, drvdata);
> > > +
> > > +     /* Parse the .dts for connections and signals */
> > > +     pdata = coresight_cti_get_platform_data(dev);
> >
> > Here I would simply call cti_plat_get_hw_data() and not instantiate a *pdata.
> > See below for more details.
> >
> > > +     if (IS_ERR(pdata)) {
> > > +             dev_info(dev, "coresight_cti_get_platform_data err\n");
> > > +             ret =  PTR_ERR(pdata);
> > > +             goto err_out;
> > > +     }
> > > +
> > > +     /* default to powered - could change on PM notifications */
> > > +     drvdata->config.hw_powered = true;
> > > +
> > > +     /* set up device name - will depend if cpu bound or otherwise */
> > > +     if (drvdata->ctidev.cpu >= 0)
> > > +             cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d",
> > > +                                            drvdata->ctidev.cpu);
> > > +     else
> > > +             cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev);
> > > +     if (!cti_desc.name) {
> > > +             ret = -ENOMEM;
> > > +             goto err_out;
> > > +     }
> > > +
> > > +     /* set up coresight component description */
> > > +     cti_desc.pdata = pdata;
> >
> > Just set this to NULL and add a check in coresight_release_platform_data() that
> > returns immediately if @pdata is NULL.  The latter should be done in a separate
> > patch preceding this one.  If someone tries to do a cti_drvdata::csdev::pdata,
> > we'll find out pretty quickly.
> >
> > With this:
> > Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> >
>
> pdata is used later in the generic coresight_register function. We
> need it to pass to this with 0 connection ports as we define
> connections differently - but we need to allow the rest of the common
> infrastructure to keep working for us.
>

I investigated this further and you are correct, the pdata is used
quite often throughout the framework to manage connections between
data components.  Provisioning for a NULL pdata would require a fair
amount of changes not related to this work.

Mathieu

> Regards
>
> Mike
>
>
> > > +     cti_desc.type = CORESIGHT_DEV_TYPE_ECT;
> > > +     cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI;
> > > +     cti_desc.ops = &cti_ops;
> > > +     cti_desc.groups = coresight_cti_groups;
> > > +     cti_desc.dev = dev;
> > > +     drvdata->csdev = coresight_register(&cti_desc);
> > > +     if (IS_ERR(drvdata->csdev)) {
> > > +             ret = PTR_ERR(drvdata->csdev);
> > > +             goto err_out;
> > > +     }
> > > +
> > > +     /* add to list of CTI devices */
> > > +     mutex_lock(&ect_mutex);
> > > +     list_add(&drvdata->node, &ect_net);
> > > +     mutex_unlock(&ect_mutex);
> > > +
> > > +     /* set up release chain */
> > > +     drvdata->csdev_release = drvdata->csdev->dev.release;
> > > +     drvdata->csdev->dev.release = cti_device_release;
> > > +
> > > +     /* all done - dec pm refcount */
> > > +     pm_runtime_put(&adev->dev);
> > > +     dev_info(&drvdata->csdev->dev, "CTI initialized\n");
> > > +     return 0;
> > > +
> > > +err_out:
> > > +     return ret;
> > > +}
> > > +
> > > +static struct amba_cs_uci_id uci_id_cti[] = {
> > > +     {
> > > +             /*  CTI UCI data */
> > > +             .devarch        = 0x47701a14, /* CTI v2 */
> > > +             .devarch_mask   = 0xfff0ffff,
> > > +             .devtype        = 0x00000014, /* maj(0x4-debug) min(0x1-ECT) */
> > > +     }
> > > +};
> > > +
> > > +static const struct amba_id cti_ids[] = {
> > > +     CS_AMBA_ID(0x000bb906), /* Coresight CTI (SoC 400), C-A72, C-A57 */
> > > +     CS_AMBA_ID(0x000bb922), /* CTI - C-A8 */
> > > +     CS_AMBA_ID(0x000bb9a8), /* CTI - C-A53 */
> > > +     CS_AMBA_ID(0x000bb9aa), /* CTI - C-A73 */
> > > +     CS_AMBA_UCI_ID(0x000bb9da, uci_id_cti), /* CTI - C-A35 */
> > > +     CS_AMBA_UCI_ID(0x000bb9ed, uci_id_cti), /* Coresight CTI (SoC 600) */
> > > +     { 0, 0},
> > > +};
> > > +
> > > +static struct amba_driver cti_driver = {
> > > +     .drv = {
> > > +             .name   = "coresight-cti",
> > > +             .owner = THIS_MODULE,
> > > +             .suppress_bind_attrs = true,
> > > +     },
> > > +     .probe          = cti_probe,
> > > +     .id_table       = cti_ids,
> > > +};
> > > +builtin_amba_driver(cti_driver);
> > > diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
> > > new file mode 100644
> > > index 000000000000..e0d476533a82
> > > --- /dev/null
> > > +++ b/drivers/hwtracing/coresight/coresight-cti.h
> > > @@ -0,0 +1,186 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +/*
> > > + * Copyright (c) 2018 Linaro Limited, All rights reserved.
> > > + * Author: Mike Leach <mike.leach@linaro.org>
> > > + */
> > > +
> > > +#ifndef _CORESIGHT_CORESIGHT_CTI_H
> > > +#define _CORESIGHT_CORESIGHT_CTI_H
> > > +
> > > +#include <asm/local.h>
> > > +#include <linux/spinlock.h>
> > > +#include "coresight-priv.h"
> > > +
> > > +/*
> > > + * Device registers
> > > + * 0x000 - 0x144: CTI programming and status
> > > + * 0xEDC - 0xEF8: CTI integration test.
> > > + * 0xF00 - 0xFFC: Coresight management registers.
> > > + */
> > > +/* CTI programming registers */
> > > +#define CTICONTROL           0x000
> > > +#define CTIINTACK            0x010
> > > +#define CTIAPPSET            0x014
> > > +#define CTIAPPCLEAR          0x018
> > > +#define CTIAPPPULSE          0x01C
> > > +#define CTIINEN(n)           (0x020 + (4 * n))
> > > +#define CTIOUTEN(n)          (0x0A0 + (4 * n))
> > > +#define CTITRIGINSTATUS              0x130
> > > +#define CTITRIGOUTSTATUS     0x134
> > > +#define CTICHINSTATUS                0x138
> > > +#define CTICHOUTSTATUS               0x13C
> > > +#define CTIGATE                      0x140
> > > +#define ASICCTL                      0x144
> > > +/* Integration test registers */
> > > +#define ITCHINACK            0xEDC /* WO CTI CSSoc 400 only*/
> > > +#define ITTRIGINACK          0xEE0 /* WO CTI CSSoc 400 only*/
> > > +#define ITCHOUT                      0xEE4 /* WO RW-600 */
> > > +#define ITTRIGOUT            0xEE8 /* WO RW-600 */
> > > +#define ITCHOUTACK           0xEEC /* RO CTI CSSoc 400 only*/
> > > +#define ITTRIGOUTACK         0xEF0 /* RO CTI CSSoc 400 only*/
> > > +#define ITCHIN                       0xEF4 /* RO */
> > > +#define ITTRIGIN             0xEF8 /* RO */
> > > +/* management registers */
> > > +#define CTIDEVAFF0           0xFA8
> > > +#define CTIDEVAFF1           0xFAC
> > > +
> > > +/*
> > > + * CTI CSSoc 600 has a max of 32 trigger signals per direction.
> > > + * CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def.
> > > + * Max of in and out defined in the DEVID register.
> > > + * - pick up actual number used from .dts parameters if present.
> > > + */
> > > +#define CTIINOUTEN_MAX               32
> > > +
> > > +/**
> > > + * Group of related trigger signals
> > > + *
> > > + * @nr_sigs: number of signals in the group.
> > > + * @used_mask: bitmask representing the signal indexes in the group.
> > > + * @sig_types: array of types for the signals, length nr_sigs.
> > > + */
> > > +struct cti_trig_grp {
> > > +     int nr_sigs;
> > > +     u32 used_mask;
> > > +     int sig_types[0];
> > > +};
> > > +
> > > +/**
> > > + * Trigger connection - connection between a CTI and other (coresight) device
> > > + * lists input and output trigger signals for the device
> > > + *
> > > + * @con_in: connected CTIIN signals for the device.
> > > + * @con_out: connected CTIOUT signals for the device.
> > > + * @con_dev: coresight device connected to the CTI, NULL if not CS device
> > > + * @con_dev_name: name of connected device (CS or CPU)
> > > + * @node: entry node in list of connections.
> > > + */
> > > +struct cti_trig_con {
> > > +     struct cti_trig_grp *con_in;
> > > +     struct cti_trig_grp *con_out;
> > > +     struct coresight_device *con_dev;
> > > +     char *con_dev_name;
> > > +     struct list_head node;
> > > +};
> > > +
> > > +/**
> > > + * struct cti_device - description of CTI device properties.
> > > + *
> > > + * @nt_trig_con: Number of external devices connected to this device.
> > > + * @ctm_id: which CTM this device is connected to (by default it is
> > > + *          assumed there is a single CTM per SoC, ID 0).
> > > + * @trig_cons: list of connections to this device.
> > > + * @cpu: CPU ID if associated with CPU, -1 otherwise.
> > > + */
> > > +struct cti_device {
> > > +     int nr_trig_con;
> > > +     u32 ctm_id;
> > > +     struct list_head trig_cons;
> > > +     int cpu;
> > > +};
> > > +
> > > +/**
> > > + * struct cti_config - configuration of the CTI device hardware
> > > + *
> > > + * @nr_trig_max: Max number of trigger signals implemented on device.
> > > + *            (max of trig_in or trig_out) - from ID register.
> > > + * @nr_ctm_channels: number of available CTM channels - from ID register.
> > > + * @enable_req_count: CTI is enabled alongside >=1 associated devices.
> > > + * @hw_enabled: true if hw is currently enabled.
> > > + * @hw_powered: true if associated cpu powered on, or no cpu.
> > > + * @trig_in_use: bitfield of in triggers registered as in use.
> > > + * @trig_out_use: bitfield of out triggers registered as in use.
> > > + * @trig_out_filter: bitfield of out triggers that are blocked if filter
> > > + *                enabled. Typically this would be dbgreq / restart on
> > > + *                a core CTI.
> > > + * @trig_filter_enable: 1 if filtering enabled.
> > > + * @xtrig_rchan_sel: channel selection for xtrigger connection show.
> > > + * @ctiappset: CTI Software application channel set.
> > > + * @ctiinout_sel: register selector for INEN and OUTEN regs.
> > > + * @ctiinen: enable input trigger to a channel.
> > > + * @ctiouten: enable output trigger from a channel.
> > > + * @ctigate: gate channel output from CTI to CTM.
> > > + * @asicctl: asic control register.
> > > + */
> > > +struct cti_config {
> > > +     /* hardware description */
> > > +     int nr_ctm_channels;
> > > +     int nr_trig_max;
> > > +
> > > +     /* cti enable control */
> > > +     atomic_t enable_req_count;
> > > +     bool hw_enabled;
> > > +     bool hw_powered;
> > > +
> > > +     /* registered triggers and filtering */
> > > +     u32 trig_in_use;
> > > +     u32 trig_out_use;
> > > +     u32 trig_out_filter;
> > > +     bool trig_filter_enable;
> > > +     u8 xtrig_rchan_sel;
> > > +
> > > +     /* cti cross trig programmable regs */
> > > +     u32 ctiappset;
> > > +     u8 ctiinout_sel;
> > > +     u32 ctiinen[CTIINOUTEN_MAX];
> > > +     u32 ctiouten[CTIINOUTEN_MAX];
> > > +     u32 ctigate;
> > > +     u32 asicctl;
> > > +};
> > > +
> > > +/**
> > > + * struct cti_drvdata - specifics for the CTI device
> > > + * @base:    Memory mapped base address for this component..
> > > + * @csdev:   Standard CoreSight device information.
> > > + * @ctidev:  Extra information needed by the CTI/CTM framework.
> > > + * @spinlock:        Control data access to one at a time.
> > > + * @config:  Configuration data for this CTI device.
> > > + * @node:    List entry of this device in the list of CTI devices.
> > > + * @csdev_release: release function for underlying coresight_device.
> > > + */
> > > +struct cti_drvdata {
> > > +     void __iomem *base;
> > > +     struct coresight_device *csdev;
> > > +     struct cti_device ctidev;
> > > +     spinlock_t spinlock;
> > > +     struct cti_config config;
> > > +     struct list_head node;
> > > +     void (*csdev_release)(struct device *dev);
> > > +};
> > > +
> > > +/* private cti driver fns & vars */
> > > +extern const struct attribute_group *coresight_cti_groups[];
> > > +int cti_add_default_connection(struct device *dev,
> > > +                            struct cti_drvdata *drvdata);
> > > +int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
> > > +                          struct cti_trig_con *tc,
> > > +                          struct coresight_device *csdev,
> > > +                          const char *assoc_dev_name);
> > > +struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
> > > +                                        int out_sigs);
> > > +int cti_enable(struct coresight_device *csdev);
> > > +int cti_disable(struct coresight_device *csdev);
> > > +struct coresight_platform_data *
> > > +coresight_cti_get_platform_data(struct device *dev);
> > > +
> > > +#endif  /* _CORESIGHT_CORESIGHT_CTI_H */
> > > diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
> > > index ef20f74c85fa..1a5fdf2710ff 100644
> > > --- a/drivers/hwtracing/coresight/coresight.c
> > > +++ b/drivers/hwtracing/coresight/coresight.c
> > > @@ -955,6 +955,9 @@ static struct device_type coresight_dev_type[] = {
> > >       {
> > >               .name = "helper",
> > >       },
> > > +     {
> > > +             .name = "ect",
> > > +     },
> > >  };
> > >
> > >  static void coresight_device_release(struct device *dev)
> > > diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> > > index 44e552de419c..b3e582d96a34 100644
> > > --- a/include/linux/coresight.h
> > > +++ b/include/linux/coresight.h
> > > @@ -41,6 +41,7 @@ enum coresight_dev_type {
> > >       CORESIGHT_DEV_TYPE_LINKSINK,
> > >       CORESIGHT_DEV_TYPE_SOURCE,
> > >       CORESIGHT_DEV_TYPE_HELPER,
> > > +     CORESIGHT_DEV_TYPE_ECT,
> > >  };
> > >
> > >  enum coresight_dev_subtype_sink {
> > > @@ -68,6 +69,12 @@ enum coresight_dev_subtype_helper {
> > >       CORESIGHT_DEV_SUBTYPE_HELPER_CATU,
> > >  };
> > >
> > > +/* Embedded Cross Trigger (ECT) sub-types */
> > > +enum coresight_dev_subtype_ect {
> > > +     CORESIGHT_DEV_SUBTYPE_ECT_NONE,
> > > +     CORESIGHT_DEV_SUBTYPE_ECT_CTI,
> > > +};
> > > +
> > >  /**
> > >   * union coresight_dev_subtype - further characterisation of a type
> > >   * @sink_subtype:    type of sink this component is, as defined
> > > @@ -78,6 +85,8 @@ enum coresight_dev_subtype_helper {
> > >   *                   by @coresight_dev_subtype_source.
> > >   * @helper_subtype:  type of helper this component is, as defined
> > >   *                   by @coresight_dev_subtype_helper.
> > > + * @ect_subtype:        type of cross trigger this component is, as
> > > + *                   defined by @coresight_dev_subtype_ect
> > >   */
> > >  union coresight_dev_subtype {
> > >       /* We have some devices which acts as LINK and SINK */
> > > @@ -87,6 +96,7 @@ union coresight_dev_subtype {
> > >       };
> > >       enum coresight_dev_subtype_source source_subtype;
> > >       enum coresight_dev_subtype_helper helper_subtype;
> > > +     enum coresight_dev_subtype_ect ect_subtype;
> > >  };
> > >
> > >  /**
> > > @@ -196,6 +206,7 @@ static struct coresight_dev_list (var) = {                                \
> > >  #define sink_ops(csdev)              csdev->ops->sink_ops
> > >  #define link_ops(csdev)              csdev->ops->link_ops
> > >  #define helper_ops(csdev)    csdev->ops->helper_ops
> > > +#define ect_ops(csdev)               csdev->ops->ect_ops
> > >
> > >  /**
> > >   * struct coresight_ops_sink - basic operations for a sink
> > > @@ -262,11 +273,23 @@ struct coresight_ops_helper {
> > >       int (*disable)(struct coresight_device *csdev, void *data);
> > >  };
> > >
> > > +/**
> > > + * struct coresight_ops_ect - Ops for an embedded cross trigger device
> > > + *
> > > + * @enable   : Enable the device
> > > + * @disable  : Disable the device
> > > + */
> > > +struct coresight_ops_ect {
> > > +     int (*enable)(struct coresight_device *csdev);
> > > +     int (*disable)(struct coresight_device *csdev);
> > > +};
> > > +
> > >  struct coresight_ops {
> > >       const struct coresight_ops_sink *sink_ops;
> > >       const struct coresight_ops_link *link_ops;
> > >       const struct coresight_ops_source *source_ops;
> > >       const struct coresight_ops_helper *helper_ops;
> > > +     const struct coresight_ops_ect *ect_ops;
> > >  };
> > >
> > >  #ifdef CONFIG_CORESIGHT
> > > --
> > > 2.17.1
> > >
>
>
>
> --
> Mike Leach
> Principal Engineer, ARM Ltd.
> Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices.
  2019-11-29 18:28   ` Suzuki Kuruppassery Poulose
  2019-11-29 21:25     ` Mathieu Poirier
@ 2019-12-05 16:33     ` Mike Leach
  1 sibling, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-12-05 16:33 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi Suzuki

On Fri, 29 Nov 2019 at 18:28, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > The CoreSight subsystem enables a path of devices from source to sink.
> > Any CTI devices associated with the path devices must be enabled at the
> > same time.
> >
> > This patch adds an associated coresight_device element to the main
> > coresight device structure, and uses this to create associations between
> > the CTI and other devices based on the device tree data. The associated
> > device element is used to enable CTI in conjunction with the path elements.
> >
> > CTI devices are reference counted so where a single CTI is associated with
> > multiple elements on the path, it will be enabled on the first associated
> > device enable, and disabled with the last associated device disable.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >   drivers/hwtracing/coresight/coresight-cti.c   | 87 +++++++++++++++++++
> >   .../hwtracing/coresight/coresight-platform.c  | 23 +++++
> >   drivers/hwtracing/coresight/coresight-priv.h  |  6 ++
> >   drivers/hwtracing/coresight/coresight.c       | 58 +++++++++++--
> >   include/linux/coresight.h                     |  5 ++
> >   5 files changed, 173 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> > index 369488dd7b8e..cf116463149a 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti.c
> > @@ -440,6 +440,90 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
> >       return err;
> >   }
> >
> > +/*
> > + * Look for a matching connection device name in the list of
> > + * connections. If found then swap in the csdev name and return
> > + * found.
> > + */
> > +static bool
> > +cti_match_con_name(struct cti_device *ctidev, const char *node_name,
> > +                const char *csdev_name)
>
> Here we actually fixup the name of the connection, rather than simply
> matching it. So it may be apt to rename this to cti_match_fixup_name()
>

Agreed.

> > +{
> > +     struct cti_trig_con *trig_con;
> > +
> > +     list_for_each_entry(trig_con, &ctidev->trig_cons, node) {
> > +             if (trig_con->con_dev_name) {
> > +                     if (!strcmp(node_name, trig_con->con_dev_name)) {
>
> Can there be duplicate node_name's ? Does it make sense to store the
> fwhandle along with the "temporary node_name" to match it later while
> fixing up ?
>
> > +                             /* match: so swap in csdev name */
> > +                             kfree(trig_con->con_dev_name);
> > +                             trig_con->con_dev_name =
> > +                                     kstrdup(csdev_name, GFP_KERNEL);
> > +                             return true;
> > +                     }
> > +             }
> > +     }
> > +     return false;
> > +}
>
>
> > +/*
> > + * Search the cti list to add an associated CTI into the supplied CS device
> > + * This will set the association if CTI declared before the CS device
> > + */
> > +void cti_add_assoc_to_csdev(struct coresight_device *csdev)
> > +{
>
> ..
>
>  > +    struct cti_drvdata *ect_item;
>  > +    struct cti_device *ctidev;
>  > +    const char *node_name = NULL, *csdev_name;
>  > +
>  > +    /* protect the list */
>  > +    mutex_lock(&ect_mutex);
>  > +
>  > +    /* exit if current is an ECT device.*/
>  > +    if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net))
>  > +            goto cti_add_done;
>  > +
>  > +    /* if we didn't find the csdev previously we used the fwnode name */
>  > +    node_name = coresight_get_fwnode_name(csdev->dev.parent);
>
> We used "cti_plat_get_node_name()" when we added the name in the
> absence of csdev in patch 7, could we not reuse the function here ?
>

Agreed - I'll remove the superfluous function.

>  > +
>  > +    if (!node_name)
>  > +            goto cti_add_done;
>  > +
>  > +    /* this is the name we want to use for the association */
>  > +    csdev_name = dev_name(&csdev->dev);
>
>
> > +
> > +     /* for each CTI in list... */
> > +     list_for_each_entry(ect_item, &ect_net, node) {
> > +             ctidev = &ect_item->ctidev;
> > +             if (cti_match_con_name(ctidev, node_name, csdev_name)) {
> > +                     /*
> > +                      * if we found a matching name then update the
> > +                      * association pointers.
> > +                      */
> > +                     csdev->ect_dev = ect_item->csdev;
> > +                     goto cti_add_done;
>
>                         break; instead ?
>
> > +             }
> > +     }
> > +cti_add_done:
> > +     mutex_unlock(&ect_mutex);
> > +}
> > +EXPORT_SYMBOL_GPL(cti_add_assoc_to_csdev);
> > +
> > +/*
> > + * Update the cross references where the associated device was found
> > + * while we were building the connection info. This will occur if the
> > + * assoc device was registered before the CTI.
> > + */
> > +static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_trig_con *tc;
> > +     struct cti_device *ctidev = &drvdata->ctidev;
> > +
> > +     list_for_each_entry(tc, &ctidev->trig_cons, node) {
> > +             if (tc->con_dev)
> > +                     tc->con_dev->ect_dev = drvdata->csdev;
> > +     }
>
> Does this need to take the coresight_mutex to avoid racing against
> a coresight_enable_path() ? Though this may be fine as long as the
> CTI driver detects that that device was not enabled.
>

Given this happens during probe, normally before trace is being
enabled this seems unlikely.
That said - the converse function happens inside the mutex, so this should too.

> Also, it looks like we have a potential issue with perf vs sysfs mode.
> The perf mode doesn't seem to take the coresight_mutex, for
> build_path/enable_path operations. This is outside the scope of this
> series though.
>
> > +}
> > +
> >   /** cti ect operations **/
> >   int cti_enable(struct coresight_device *csdev)
> >   {
> > @@ -574,6 +658,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> >       drvdata->csdev_release = drvdata->csdev->dev.release;
> >       drvdata->csdev->dev.release = cti_device_release;
> >
> > +     /* set any cross references */
> > +     cti_update_conn_xrefs(drvdata);
> > +
>         /* all done - dec pm refcount */
> >       pm_runtime_put(&adev->dev);
> >       dev_info(&drvdata->csdev->dev, "CTI initialized\n");
> > diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
> > index 3c5bee429105..6721cb1af5fe 100644
> > --- a/drivers/hwtracing/coresight/coresight-platform.c
> > +++ b/drivers/hwtracing/coresight/coresight-platform.c
> > @@ -293,6 +293,12 @@ static int of_get_coresight_platform_data(struct device *dev,
> >
> >       return 0;
> >   }
> > +
> > +static inline const char *of_coresight_get_node_name(struct device *dev)
> > +{
> > +     return dev->of_node->full_name;
> > +}
> > +
> >   #else
> >   static inline int
> >   of_get_coresight_platform_data(struct device *dev,
> > @@ -305,6 +311,11 @@ static inline int of_coresight_get_cpu(struct device *dev)
> >   {
> >       return -ENODEV;
> >   }
> > +
> > +static inline const char *of_coresight_get_node_name(struct device *dev)
> > +{
> > +     return NULL;
> > +}
> >   #endif
> >
> >   #ifdef CONFIG_ACPI
> > @@ -766,6 +777,18 @@ static inline int acpi_coresight_get_cpu(struct device *dev)
> >   }
> >   #endif
> >
> > +const char *coresight_get_fwnode_name(struct device *dev)
>
> As mentioned above, please could we reuse the name helper we used
> during the insertion rather than introducing a new wrapper which
> effectively does the same thing ?
>

Agreed.

> > +{
> > +     const char *node_name = NULL;
> > +     struct fwnode_handle *fwnode = dev_fwnode(dev);
> > +
> > +     if (is_of_node(fwnode))
> > +             node_name = of_coresight_get_node_name(dev);
> > +
> > +     return node_name;
> > +}
> > +EXPORT_SYMBOL_GPL(coresight_get_fwnode_name);
>
> Why does this get exported ? If a following patch needs it, you may
> always do that when you need it.
>
>
> Cheers
> Suzuki

Thanks


Mike

--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices.
  2019-11-25 22:45   ` Mathieu Poirier
@ 2019-12-05 16:33     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-12-05 16:33 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Suzuki K. Poulose

HI Mathieu,

Will fix as requested.

Thanks

Mike


On Mon, 25 Nov 2019 at 22:45, Mathieu Poirier
<mathieu.poirier@linaro.org> wrote:
>
> On Tue, Nov 19, 2019 at 11:19:06PM +0000, Mike Leach wrote:
> > The CoreSight subsystem enables a path of devices from source to sink.
> > Any CTI devices associated with the path devices must be enabled at the
> > same time.
> >
> > This patch adds an associated coresight_device element to the main
> > coresight device structure, and uses this to create associations between
> > the CTI and other devices based on the device tree data. The associated
> > device element is used to enable CTI in conjunction with the path elements.
> >
> > CTI devices are reference counted so where a single CTI is associated with
> > multiple elements on the path, it will be enabled on the first associated
> > device enable, and disabled with the last associated device disable.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >  drivers/hwtracing/coresight/coresight-cti.c   | 87 +++++++++++++++++++
> >  .../hwtracing/coresight/coresight-platform.c  | 23 +++++
> >  drivers/hwtracing/coresight/coresight-priv.h  |  6 ++
> >  drivers/hwtracing/coresight/coresight.c       | 58 +++++++++++--
> >  include/linux/coresight.h                     |  5 ++
> >  5 files changed, 173 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> > index 369488dd7b8e..cf116463149a 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti.c
> > @@ -440,6 +440,90 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
> >       return err;
> >  }
> >
> > +/*
> > + * Look for a matching connection device name in the list of
> > + * connections. If found then swap in the csdev name and return
> > + * found.
> > + */
> > +static bool
> > +cti_match_con_name(struct cti_device *ctidev, const char *node_name,
> > +                const char *csdev_name)
> > +{
> > +     struct cti_trig_con *trig_con;
> > +
> > +     list_for_each_entry(trig_con, &ctidev->trig_cons, node) {
> > +             if (trig_con->con_dev_name) {
> > +                     if (!strcmp(node_name, trig_con->con_dev_name)) {
> > +                             /* match: so swap in csdev name */
> > +                             kfree(trig_con->con_dev_name);
> > +                             trig_con->con_dev_name =
> > +                                     kstrdup(csdev_name, GFP_KERNEL);
> > +                             return true;
> > +                     }
> > +             }
> > +     }
> > +     return false;
> > +}
> > +
> > +/*
> > + * Search the cti list to add an associated CTI into the supplied CS device
> > + * This will set the association if CTI declared before the CS device
> > + */
> > +void cti_add_assoc_to_csdev(struct coresight_device *csdev)
> > +{
> > +     struct cti_drvdata *ect_item;
> > +     struct cti_device *ctidev;
> > +     const char *node_name = NULL, *csdev_name;
> > +
> > +     /* protect the list */
> > +     mutex_lock(&ect_mutex);
> > +
> > +     /* exit if current is an ECT device.*/
> > +     if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net))
> > +             goto cti_add_done;
> > +
> > +     /* if we didn't find the csdev previously we used the fwnode name */
> > +     node_name = coresight_get_fwnode_name(csdev->dev.parent);
> > +
> > +     if (!node_name)
> > +             goto cti_add_done;
> > +
> > +     /* this is the name we want to use for the association */
> > +     csdev_name = dev_name(&csdev->dev);
> > +
> > +     /* for each CTI in list... */
> > +     list_for_each_entry(ect_item, &ect_net, node) {
> > +             ctidev = &ect_item->ctidev;
> > +             if (cti_match_con_name(ctidev, node_name, csdev_name)) {
> > +                     /*
> > +                      * if we found a matching name then update the
> > +                      * association pointers.
> > +                      */
> > +                     csdev->ect_dev = ect_item->csdev;
> > +                     goto cti_add_done;
> > +             }
> > +     }
> > +cti_add_done:
> > +     mutex_unlock(&ect_mutex);
> > +}
> > +EXPORT_SYMBOL_GPL(cti_add_assoc_to_csdev);
> > +
> > +/*
> > + * Update the cross references where the associated device was found
> > + * while we were building the connection info. This will occur if the
> > + * assoc device was registered before the CTI.
> > + */
> > +static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_trig_con *tc;
> > +     struct cti_device *ctidev = &drvdata->ctidev;
> > +
> > +     list_for_each_entry(tc, &ctidev->trig_cons, node) {
> > +             if (tc->con_dev)
> > +                     tc->con_dev->ect_dev = drvdata->csdev;
> > +     }
> > +}
> > +
> >  /** cti ect operations **/
> >  int cti_enable(struct coresight_device *csdev)
> >  {
> > @@ -574,6 +658,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> >       drvdata->csdev_release = drvdata->csdev->dev.release;
> >       drvdata->csdev->dev.release = cti_device_release;
> >
> > +     /* set any cross references */
> > +     cti_update_conn_xrefs(drvdata);
> > +
> >       /* all done - dec pm refcount */
> >       pm_runtime_put(&adev->dev);
> >       dev_info(&drvdata->csdev->dev, "CTI initialized\n");
> > diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
> > index 3c5bee429105..6721cb1af5fe 100644
> > --- a/drivers/hwtracing/coresight/coresight-platform.c
> > +++ b/drivers/hwtracing/coresight/coresight-platform.c
> > @@ -293,6 +293,12 @@ static int of_get_coresight_platform_data(struct device *dev,
> >
> >       return 0;
> >  }
> > +
> > +static inline const char *of_coresight_get_node_name(struct device *dev)
> > +{
> > +     return dev->of_node->full_name;
> > +}
> > +
> >  #else
> >  static inline int
> >  of_get_coresight_platform_data(struct device *dev,
> > @@ -305,6 +311,11 @@ static inline int of_coresight_get_cpu(struct device *dev)
> >  {
> >       return -ENODEV;
> >  }
> > +
> > +static inline const char *of_coresight_get_node_name(struct device *dev)
> > +{
> > +     return NULL;
> > +}
> >  #endif
> >
> >  #ifdef CONFIG_ACPI
> > @@ -766,6 +777,18 @@ static inline int acpi_coresight_get_cpu(struct device *dev)
> >  }
> >  #endif
> >
> > +const char *coresight_get_fwnode_name(struct device *dev)
> > +{
> > +     const char *node_name = NULL;
> > +     struct fwnode_handle *fwnode = dev_fwnode(dev);
> > +
> > +     if (is_of_node(fwnode))
> > +             node_name = of_coresight_get_node_name(dev);
> > +
> > +     return node_name;
> > +}
> > +EXPORT_SYMBOL_GPL(coresight_get_fwnode_name);
> > +
> >  int coresight_get_cpu(struct device *dev)
> >  {
> >       if (is_of_node(dev->fwnode))
> > diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> > index aba6b789c969..484e5ec593bb 100644
> > --- a/drivers/hwtracing/coresight/coresight-priv.h
> > +++ b/drivers/hwtracing/coresight/coresight-priv.h
> > @@ -162,6 +162,12 @@ static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
> >  static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
> >  #endif
> >
> > +#ifdef CONFIG_CORESIGHT_CTI
> > +extern void cti_add_assoc_to_csdev(struct coresight_device *csdev);
> > +#else
> > +static inline void cti_add_assoc_to_csdev(struct coresight_device *csdev) {}
> > +#endif
> > +
> >  /*
> >   * Macros and inline functions to handle CoreSight UCI data and driver
> >   * private data in AMBA ID table entries, and extract data values.
> > diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
> > index 1a5fdf2710ff..7657be009246 100644
> > --- a/drivers/hwtracing/coresight/coresight.c
> > +++ b/drivers/hwtracing/coresight/coresight.c
> > @@ -216,6 +216,31 @@ void coresight_disclaim_device(void __iomem *base)
> >       CS_LOCK(base);
> >  }
> >
> > +/* enable or disable an associated CTI device of the supplied CS device */
> > +static int
> > +coresight_control_assoc_ectdev(struct coresight_device *csdev, bool enable)
> > +{
> > +     int ect_ret = 0;
> > +     struct coresight_device *ect_csdev = csdev->ect_dev;
> > +
> > +     if (!ect_csdev)
> > +             return 0;
> > +
> > +     if (enable) {
> > +             if (ect_ops(ect_csdev)->enable)
> > +                     ect_ret = ect_ops(ect_csdev)->enable(ect_csdev);
> > +     } else {
> > +             if (ect_ops(ect_csdev)->disable)
> > +                     ect_ret = ect_ops(ect_csdev)->disable(ect_csdev);
> > +     }
> > +
> > +     /* output warning if ECT enable is preventing trace operation */
> > +     if (ect_ret)
> > +             dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n",
> > +              dev_name(&ect_csdev->dev), enable ? "enable" : "disable");
>
> Indentation problem - please replace with:
>
>                 dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n",
>                          dev_name(&ect_csdev->dev),
>                          enable ? "enable" : "disable");
>
> > +     return ect_ret;
> > +}
> > +
> >  static int coresight_enable_sink(struct coresight_device *csdev,
> >                                u32 mode, void *data)
> >  {
> > @@ -228,11 +253,15 @@ static int coresight_enable_sink(struct coresight_device *csdev,
> >       if (!sink_ops(csdev)->enable)
> >               return -EINVAL;
> >
> > -     ret = sink_ops(csdev)->enable(csdev, mode, data);
> > +     ret = coresight_control_assoc_ectdev(csdev, true);
> >       if (ret)
> >               return ret;
> > +     ret = sink_ops(csdev)->enable(csdev, mode, data);
> > +     if (ret) {
> > +             coresight_control_assoc_ectdev(csdev, false);
> > +             return ret;
> > +     }
> >       csdev->enable = true;
> > -
>
> Unneeded modification.
>
> With the above changes:
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
> >       return 0;
> >  }
> >
> > @@ -246,6 +275,7 @@ static void coresight_disable_sink(struct coresight_device *csdev)
> >       ret = sink_ops(csdev)->disable(csdev);
> >       if (ret)
> >               return;
> > +     coresight_control_assoc_ectdev(csdev, false);
> >       csdev->enable = false;
> >  }
> >
> > @@ -269,8 +299,15 @@ static int coresight_enable_link(struct coresight_device *csdev,
> >       if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0)
> >               return outport;
> >
> > -     if (link_ops(csdev)->enable)
> > -             ret = link_ops(csdev)->enable(csdev, inport, outport);
> > +     if (link_ops(csdev)->enable) {
> > +             ret = coresight_control_assoc_ectdev(csdev, true);
> > +             if (!ret) {
> > +                     ret = link_ops(csdev)->enable(csdev, inport, outport);
> > +                     if (ret)
> > +                             coresight_control_assoc_ectdev(csdev, false);
> > +             }
> > +     }
> > +
> >       if (!ret)
> >               csdev->enable = true;
> >
> > @@ -300,8 +337,10 @@ static void coresight_disable_link(struct coresight_device *csdev,
> >               nr_conns = 1;
> >       }
> >
> > -     if (link_ops(csdev)->disable)
> > +     if (link_ops(csdev)->disable) {
> >               link_ops(csdev)->disable(csdev, inport, outport);
> > +             coresight_control_assoc_ectdev(csdev, false);
> > +     }
> >
> >       for (i = 0; i < nr_conns; i++)
> >               if (atomic_read(&csdev->refcnt[i]) != 0)
> > @@ -322,9 +361,14 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
> >
> >       if (!csdev->enable) {
> >               if (source_ops(csdev)->enable) {
> > -                     ret = source_ops(csdev)->enable(csdev, NULL, mode);
> > +                     ret = coresight_control_assoc_ectdev(csdev, true);
> >                       if (ret)
> >                               return ret;
> > +                     ret = source_ops(csdev)->enable(csdev, NULL, mode);
> > +                     if (ret) {
> > +                             coresight_control_assoc_ectdev(csdev, false);
> > +                             return ret;
> > +                     };
> >               }
> >               csdev->enable = true;
> >       }
> > @@ -347,6 +391,7 @@ static bool coresight_disable_source(struct coresight_device *csdev)
> >       if (atomic_dec_return(csdev->refcnt) == 0) {
> >               if (source_ops(csdev)->disable)
> >                       source_ops(csdev)->disable(csdev, NULL);
> > +             coresight_control_assoc_ectdev(csdev, false);
> >               csdev->enable = false;
> >       }
> >       return !csdev->enable;
> > @@ -1252,6 +1297,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
> >
> >       coresight_fixup_device_conns(csdev);
> >       coresight_fixup_orphan_conns(csdev);
> > +     cti_add_assoc_to_csdev(csdev);
> >
> >       mutex_unlock(&coresight_mutex);
> >
> > diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> > index b3e582d96a34..b5dc9baf0c58 100644
> > --- a/include/linux/coresight.h
> > +++ b/include/linux/coresight.h
> > @@ -163,6 +163,8 @@ struct coresight_connection {
> >   *           activated but not yet enabled.  Enabling for a _sink_
> >   *           appens when a source has been selected for that it.
> >   * @ea:              Device attribute for sink representation under PMU directory.
> > + * @ect_dev: Associated cross trigger device. Not part of the trace data
> > + *           path or connections.
> >   */
> >  struct coresight_device {
> >       struct coresight_platform_data *pdata;
> > @@ -176,6 +178,8 @@ struct coresight_device {
> >       /* sink specific fields */
> >       bool activated; /* true only if a sink is part of a path */
> >       struct dev_ext_attribute *ea;
> > +     /* cross trigger handling */
> > +     struct coresight_device *ect_dev;
> >  };
> >
> >  /*
> > @@ -341,5 +345,6 @@ static inline bool coresight_loses_context_with_cpu(struct device *dev)
> >  extern int coresight_get_cpu(struct device *dev);
> >
> >  struct coresight_platform_data *coresight_get_platform_data(struct device *dev);
> > +extern const char *coresight_get_fwnode_name(struct device *dev);
> >
> >  #endif
> > --
> > 2.17.1
> >



--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 09/14] coresight: cti: Add connection information to sysfs
  2019-11-27 18:09   ` Mathieu Poirier
@ 2019-12-06 16:24     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-12-06 16:24 UTC (permalink / raw)
  To: Mathieu Poirier
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Suzuki K. Poulose

Hi Mathieu,

On Wed, 27 Nov 2019 at 18:09, Mathieu Poirier
<mathieu.poirier@linaro.org> wrote:
>
> On Tue, Nov 19, 2019 at 11:19:07PM +0000, Mike Leach wrote:
> > Dynamically adds sysfs attributes for all connections defined in the CTI.
> >
> > Each connection has a triggers<N> sub-directory with name, in_signals,
> > in_types, out_signals and out_types as read-only parameters in the
> > directory. in_ or out_ parameters may be omitted if there are no in or
> > out signals for the connection.
> >
> > Additionally each device has a nr_cons in the connections sub-directory.
> >
> > This allows clients to explore the connection and trigger signal details
> > without needing to refer to device tree or specification of the device.
> >
> > Standardised type information is provided for certain common functions -
> > e.g. snk_full for a trigger from a sink indicating full. Otherwise type
> > defaults to genio.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >  .../hwtracing/coresight/coresight-cti-sysfs.c | 376 +++++++++++++++++-
> >  drivers/hwtracing/coresight/coresight-cti.c   |  13 +-
> >  drivers/hwtracing/coresight/coresight-cti.h   |  11 +-
> >  3 files changed, 396 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > index f800402f73da..91986732506f 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > @@ -8,6 +8,67 @@
> >
> >  #include "coresight-cti.h"
> >
> > +/*
> > + * Declare the number of static declared attribute groups
> > + * Value includes groups + NULL value at end of table.
> > + */
> > +#define CORESIGHT_CTI_STATIC_GROUPS_MAX 5
> > +
> > +/*
> > + * List of trigger signal type names. Match the constants declared in
> > + * include\dt-bindings\arm\coresight-cti-dt.h
> > + */
> > +static const char * const sig_type_names[] = {
> > +     "genio",        /* GEN_IO */
> > +     "intreq",       /* GEN_INTREQ */
> > +     "intack",       /* GEN_INTACK */
> > +     "haltreq",      /* GEN_HALTREQ */
> > +     "restartreq",   /* GEN_RESTARTREQ */
> > +     "pe_edbgreq",   /* PE_EDBGREQ */
> > +     "pe_dbgrestart",/* PE_DBGRESTART */
> > +     "pe_ctiirq",    /* PE_CTIIRQ */
> > +     "pe_pmuirq",    /* PE_PMUIRQ */
> > +     "pe_dbgtrigger",/* PE_DBGTRIGGER */
> > +     "etm_extout",   /* ETM_EXTOUT */
> > +     "etm_extin",    /* ETM_EXTIN */
> > +     "snk_full",     /* SNK_FULL */
> > +     "snk_acqcomp",  /* SNK_ACQCOMP */
> > +     "snk_flushcomp",/* SNK_FLUSHCOMP */
> > +     "snk_flushin",  /* SNK_FLUSHIN */
> > +     "snk_trigin",   /* SNK_TRIGIN */
> > +     "stm_asyncout", /* STM_ASYNCOUT */
> > +     "stm_tout_spte",/* STM_TOUT_SPTE */
> > +     "stm_tout_sw",  /* STM_TOUT_SW */
> > +     "stm_tout_hete",/* STM_TOUT_HETE */
> > +     "stm_hwevent",  /* STM_HWEVENT */
> > +     "ela_tstart",   /* ELA_TSTART */
> > +     "ela_tstop",    /* ELA_TSTOP */
> > +     "ela_dbgreq",   /* ELA_DBGREQ */
> > +};
> > +
> > +/* Show function pointer used in the connections dynamic declared attributes*/
> > +typedef ssize_t (*p_show_fn)(struct device *dev, struct device_attribute *attr,
> > +                          char *buf);
> > +
> > +/* Connection attribute types */
> > +enum cti_conn_attr_type {
> > +     CTI_CON_ATTR_NAME,
> > +     CTI_CON_ATTR_TRIGIN_SIG,
> > +     CTI_CON_ATTR_TRIGOUT_SIG,
> > +     CTI_CON_ATTR_TRIGIN_TYPES,
> > +     CTI_CON_ATTR_TRIGOUT_TYPES,
> > +     CTI_CON_ATTR_MAX,
> > +};
> > +
> > +/* Names for the connection attributes */
> > +static const char * const con_attr_names[CTI_CON_ATTR_MAX] = {
> > +     "name",
> > +     "in_signals",
> > +     "out_signals",
> > +     "in_types",
> > +     "out_types",
> > +};
> > +
> >  /* basic attributes */
> >  static ssize_t enable_show(struct device *dev,
> >                          struct device_attribute *attr,
> > @@ -66,10 +127,21 @@ static ssize_t ctmid_show(struct device *dev,
> >  }
> >  static DEVICE_ATTR_RO(ctmid);
> >
> > +static ssize_t nr_trigger_cons_show(struct device *dev,
> > +                                 struct device_attribute *attr,
> > +                                 char *buf)
> > +{
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +
> > +     return scnprintf(buf, PAGE_SIZE, "%d\n", drvdata->ctidev.nr_trig_con);
> > +}
> > +static DEVICE_ATTR_RO(nr_trigger_cons);
> > +
> >  /* attribute and group sysfs tables. */
> >  static struct attribute *coresight_cti_attrs[] = {
> >       &dev_attr_enable.attr,
> >       &dev_attr_ctmid.attr,
> > +     &dev_attr_nr_trigger_cons.attr,
>
> I think it looks much getter that way - thanks for moving that.
>
> >       NULL,
> >  };
> >
> > @@ -818,7 +890,306 @@ static struct attribute *coresight_cti_channel_attrs[] = {
> >       NULL,
> >  };
> >
> > -/* sysfs groups */
> > +/* Create the connections trigger groups and attrs dynamically */
> > +/*
> > + * Each connection has dynamic group triggers<N> + name, trigin/out sigs/types
> > + * attributes, + each device has static nr_trigger_cons giving the number
> > + * of groups. e.g. in sysfs:-
> > + * /cti_<name>/triggers0
> > + * /cti_<name>/triggers1
> > + * /cti_<name>/nr_trigger_cons
> > + * where nr_trigger_cons = 2
> > + */
> > +static ssize_t con_name_show(struct device *dev,
> > +                          struct device_attribute *attr,
> > +                          char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +
> > +     return scnprintf(buf, PAGE_SIZE, "%s\n", con->con_dev_name);
> > +}
> > +
> > +static ssize_t trigin_sig_show(struct device *dev,
> > +                            struct device_attribute *attr,
> > +                            char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +     struct cti_config *cfg = &drvdata->config;
> > +     unsigned long mask = con->con_in->used_mask;
> > +
> > +     return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
> > +}
> > +
> > +static ssize_t trigout_sig_show(struct device *dev,
> > +                             struct device_attribute *attr,
> > +                             char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +     struct cti_config *cfg = &drvdata->config;
> > +     unsigned long mask = con->con_out->used_mask;
> > +
> > +     return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
> > +}
> > +
> > +/* convert a sig type id to a name */
> > +static const char *
> > +cti_sig_type_name(struct cti_trig_con *con, int used_count, bool in)
> > +{
> > +     int idx = 0;
> > +     struct cti_trig_grp *grp = in ? con->con_in : con->con_out;
> > +
> > +     if (grp->sig_types) {
> > +             if (used_count < grp->nr_sigs)
> > +                     idx = grp->sig_types[used_count];
> > +     }
> > +     return sig_type_names[idx];
> > +}
> > +
> > +static ssize_t trigin_type_show(struct device *dev,
> > +                             struct device_attribute *attr,
> > +                             char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +     int sig_idx, used = 0, b_sz = PAGE_SIZE;
> > +     const char *name;
> > +
> > +     for (sig_idx = 0; sig_idx < con->con_in->nr_sigs; sig_idx++) {
> > +             name = cti_sig_type_name(con, sig_idx, true);
> > +             used += scnprintf(buf + used, b_sz - used, "%s ", name);
> > +     }
> > +     used += scnprintf(buf + used, b_sz - used, "\n");
> > +     return used;
> > +}
> > +
> > +static ssize_t trigout_type_show(struct device *dev,
> > +                              struct device_attribute *attr,
> > +                              char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +     int sig_idx, used = 0, b_sz = PAGE_SIZE;
> > +     const char *name;
> > +
> > +     for (sig_idx = 0; sig_idx < con->con_out->nr_sigs; sig_idx++) {
> > +             name = cti_sig_type_name(con, sig_idx, false);
> > +             used += scnprintf(buf + used, b_sz - used, "%s ", name);
> > +     }
> > +     used += scnprintf(buf + used, b_sz - used, "\n");
> > +     return used;
> > +}
> > +
> > +/*
> > + * Array of show function names declared above to allow selection
> > + * for the connection attributes
> > + */
> > +static p_show_fn show_fns[CTI_CON_ATTR_MAX] = {
> > +     con_name_show,
> > +     trigin_sig_show,
> > +     trigout_sig_show,
> > +     trigin_type_show,
> > +     trigout_type_show,
> > +};
> > +
> > +static int cti_create_con_sysfs_attr(struct cti_trig_con *con,
> > +                                  enum cti_conn_attr_type attr_type,
> > +                                  int attr_idx)
> > +{
> > +     struct dev_ext_attribute *dev_ext_attr = 0;
> > +     char *name = 0;
> > +
> > +     dev_ext_attr = kzalloc(sizeof(struct dev_ext_attribute), GFP_KERNEL);
> > +     if (dev_ext_attr) {
> > +             name = kstrdup(con_attr_names[attr_type], GFP_KERNEL);
> > +             if (name) {
> > +                     /* fill out the underlying attribute struct */
> > +                     dev_ext_attr->attr.attr.name = name;
> > +                     dev_ext_attr->attr.attr.mode = 0444;
> > +
> > +                     /* now the device_attribute struct */
> > +                     dev_ext_attr->attr.show = show_fns[attr_type];
> > +             } else {
> > +                     kfree(dev_ext_attr);
> > +                     return -ENOMEM;
> > +             }
> > +     } else {
> > +             return -ENOMEM;
> > +     }
> > +     dev_ext_attr->var = con;
> > +     con->con_attrs[attr_idx] = &dev_ext_attr->attr.attr;
> > +     return 0;
> > +}
> > +
> > +static struct attribute_group *
> > +cti_create_con_sysfs_group(struct cti_device *ctidev, int con_idx,
> > +                        struct cti_trig_con *con)
> > +{
> > +     struct attribute_group *group = NULL;
> > +
> > +     group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
> > +     if (!group)
> > +             return NULL;
> > +
> > +     group->name = kasprintf(GFP_KERNEL, "triggers%d", con_idx);
> > +     if (!group->name) {
> > +             kfree(group);
> > +             return NULL;
> > +     }
> > +
> > +     ctidev->con_groups[con_idx + CORESIGHT_CTI_STATIC_GROUPS_MAX - 1]
> > +             = group;
>
>         idx = con_idx + CORESIGHT_CTI_STATIC_GROUPS_MAX - 1;
>         ctidev->con_groups[idx] = group;
>
OK

> > +     con->attr_group = group;
> > +     return group;
> > +}
> > +
> > +/* create a triggers connection group and the attributes for that group */
> > +static int cti_create_con_attr_set(int con_idx, struct cti_device *ctidev,
> > +                                struct cti_trig_con *con)
> > +{
> > +     struct attribute_group *attr_group = NULL;
> > +     int attr_idx = 0;
> > +     int err = -ENOMEM;
> > +
> > +     attr_group = cti_create_con_sysfs_group(ctidev, con_idx, con);
> > +     if (!attr_group)
> > +             return -ENOMEM;
> > +
> > +     /* allocate NULL terminated array of attributes */
> > +     con->con_attrs = kcalloc(CTI_CON_ATTR_MAX + 1,
> > +                              sizeof(struct attribute *),
> > +                              GFP_KERNEL);
> > +     if (!con->con_attrs)
> > +             return -ENOMEM;
> > +
> > +     err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_NAME, attr_idx++);
> > +     if (err)
> > +             return err;
> > +
> > +     if (con->con_in->nr_sigs > 0) {
>
> I think we should check the validity of con->con_in before proceeding,
> especially if people can do their HW however they want.  Same for con->con_out
> below.
>

When we create con, we also create con->con_in and con->con_out as
zero init. So this is safe and all the handling code is much simpler.
The implementation dependent issues are thus handled in the con_in /
con_out structure attribute values.

> > +             err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_SIG,
> > +                                             attr_idx++);
> > +             if (err)
> > +                     return err;
> > +
> > +             err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_TYPES,
> > +                                             attr_idx++);
> > +             if (err)
> > +                     return err;
> > +     }
> > +
> > +     if (con->con_in->nr_sigs > 0) {
>
>         if (con->con_out->nr_sigs > 0)
>
Good spot!

> > +             err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_SIG,
> > +                                             attr_idx++);
> > +             if (err)
> > +                     return err;
> > +
> > +             err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_TYPES,
> > +                                             attr_idx++);
> > +             if (err)
> > +                     return err;
> > +     }
> > +     attr_group->attrs = con->con_attrs;
> > +     return 0;
> > +}
> > +
> > +/* create the array of group pointers for the CTI sysfs groups */
> > +int cti_create_cons_groups(struct cti_device *ctidev)
> > +{
> > +     int i, nr_groups;
> > +
> > +     /* nr groups - dynamic + static + NULL terminator */
> > +     nr_groups = ctidev->nr_trig_con + CORESIGHT_CTI_STATIC_GROUPS_MAX;
> > +     ctidev->con_groups = kcalloc(nr_groups,
> > +                                  sizeof(struct attribute_group *),
> > +                                  GFP_KERNEL);
> > +     if (!ctidev->con_groups)
> > +             return -ENOMEM;
> > +
> > +     /* populate first locations with the static set of groups */
> > +     for (i = 0; i < (CORESIGHT_CTI_STATIC_GROUPS_MAX - 1); i++)
> > +             ctidev->con_groups[i] = coresight_cti_groups[i];
> > +
> > +     return 0;
> > +}
> > +
> > +int cti_create_cons_sysfs(struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_device *ctidev = &drvdata->ctidev;
> > +     int err, con_idx = 0;
> > +     struct cti_trig_con *tc = NULL;
> > +
> > +     err = cti_create_cons_groups(ctidev);
> > +     if (err)
> > +             return err;
> > +
> > +     /* add dynamic set for each connection */
> > +     list_for_each_entry(tc, &ctidev->trig_cons, node) {
> > +             err = cti_create_con_attr_set(con_idx++, ctidev, tc);
> > +             if (err)
> > +                     goto cons_sysfs_err;
> > +     }
> > +     return 0;
> > +
> > +cons_sysfs_err:
> > +     cti_destroy_cons_sysfs(ctidev);
> > +     return err;
> > +}
> > +
> > +void cti_free_con_attr(struct attribute *con_attr)
> > +{
> > +     struct device_attribute *dattr =
> > +             container_of(con_attr, struct device_attribute, attr);
> > +     struct dev_ext_attribute *dev_ext_attr =
> > +             container_of(dattr, struct dev_ext_attribute, attr);
> > +     kfree(con_attr->name);
> > +     kfree(dev_ext_attr);
> > +}
> > +
> > +void cti_free_con_group(struct attribute_group *attr_group)
> > +{
> > +     if (attr_group) {
> > +             kfree(attr_group->name);
> > +             kfree(attr_group);
> > +     }
> > +}
> > +
> > +void cti_destroy_cons_attr_set(int con_idx, struct cti_device *ctidev,
> > +                            struct cti_trig_con *con)
> > +{
> > +     int i;
> > +
> > +     if (con->con_attrs) {
> > +             for (i = 0; i < CTI_CON_ATTR_MAX; i++) {
> > +                     if (con->con_attrs[i])
> > +                             cti_free_con_attr(con->con_attrs[i]);
> > +             }
> > +             kfree(con->con_attrs);
> > +     }
> > +     cti_free_con_group(con->attr_group);
> > +}
> > +
> > +void cti_destroy_cons_sysfs(struct cti_device *ctidev)
> > +{
> > +     struct cti_trig_con *tc;
> > +     int con_idx = 0;
> > +
> > +     list_for_each_entry(tc, &ctidev->trig_cons, node) {
> > +             cti_destroy_cons_attr_set(con_idx++, ctidev, tc);
> > +     }
> > +     kfree(ctidev->con_groups);
> > +}
> > +
> > +/* attribute and group sysfs tables. */
> >  static const struct attribute_group coresight_cti_group = {
> >       .attrs = coresight_cti_attrs,
> >  };
> > @@ -838,7 +1209,8 @@ static const struct attribute_group coresight_cti_channels_group = {
> >       .name = "channels",
> >  };
> >
> > -const struct attribute_group *coresight_cti_groups[] = {
> > +const struct attribute_group *
> > +coresight_cti_groups[CORESIGHT_CTI_STATIC_GROUPS_MAX] = {
> >       &coresight_cti_group,
> >       &coresight_cti_mgmt_group,
> >       &coresight_cti_regs_group,
> > diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> > index cf116463149a..c3d63cc53bdd 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti.c
> > @@ -561,6 +561,9 @@ static void cti_device_release(struct device *dev)
> >
> >       mutex_lock(&ect_mutex);
> >
> > +     /* clear the dynamic sysfs associate with connections */
> > +     cti_destroy_cons_sysfs(&drvdata->ctidev);
> > +
> >       /* remove from the list */
> >       list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
> >               if (ect_item == drvdata) {
> > @@ -636,12 +639,20 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> >               goto err_out;
> >       }
> >
> > +     /* create dynamic attributes for connections */
> > +     ret = cti_create_cons_sysfs(drvdata);
> > +     if (ret) {
> > +             pr_err("%s: create dynamic sysfs entries failed\n",
> > +                    cti_desc.name);
> > +             goto err_out;
> > +     }
> > +
> >       /* set up coresight component description */
> >       cti_desc.pdata = pdata;
> >       cti_desc.type = CORESIGHT_DEV_TYPE_ECT;
> >       cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI;
> >       cti_desc.ops = &cti_ops;
> > -     cti_desc.groups = coresight_cti_groups;
> > +     cti_desc.groups = drvdata->ctidev.con_groups;
> >       cti_desc.dev = dev;
> >       drvdata->csdev = coresight_register(&cti_desc);
> >       if (IS_ERR(drvdata->csdev)) {
> > diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
> > index 9a22f6fcad65..dc5b265acf5e 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti.h
> > +++ b/drivers/hwtracing/coresight/coresight-cti.h
> > @@ -74,6 +74,8 @@ struct cti_trig_grp {
> >   * @con_dev: coresight device connected to the CTI, NULL if not CS device
> >   * @con_dev_name: name of connected device (CS or CPU)
> >   * @node: entry node in list of connections.
> > + * @con_attrs: Dynamic sysfs attributes specific to this connection.
> > + * @attr_group: Dynamic attribute group created for this connection.
> >   */
> >  struct cti_trig_con {
> >       struct cti_trig_grp *con_in;
> > @@ -81,6 +83,8 @@ struct cti_trig_con {
> >       struct coresight_device *con_dev;
> >       char *con_dev_name;
> >       struct list_head node;
> > +     struct attribute **con_attrs;
> > +     struct attribute_group *attr_group;
> >  };
> >
> >  /**
> > @@ -91,12 +95,15 @@ struct cti_trig_con {
> >   *          assumed there is a single CTM per SoC, ID 0).
> >   * @trig_cons: list of connections to this device.
> >   * @cpu: CPU ID if associated with CPU, -1 otherwise.
> > + * @con_groups: combined static and dynamic sysfs groups for trigger
> > + *           connections.
> >   */
> >  struct cti_device {
> >       int nr_trig_con;
> >       u32 ctm_id;
> >       struct list_head trig_cons;
> >       int cpu;
> > +     const struct attribute_group **con_groups;
> >  };
> >
> >  /**
> > @@ -111,7 +118,7 @@ struct cti_device {
> >   * @trig_in_use: bitfield of in triggers registered as in use.
> >   * @trig_out_use: bitfield of out triggers registered as in use.
> >   * @trig_out_filter: bitfield of out triggers that are blocked if filter
> > - *                enabled. Typically this would be dbgreq / restart on
> > + *                enabled. Typically this would be dbgreq / restart on
>
> Spurious change.
>
Looks like a whitespace issue - will address in earlier patch.

> With the above:
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
> >   *                a core CTI.
> >   * @trig_filter_enable: 1 if filtering enabled.
> >   * @xtrig_rchan_sel: channel selection for xtrigger connection show.
> > @@ -214,6 +221,8 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
> >                       u32 channel_idx);
> >  int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
> >                     u32 channel_idx);
> > +int cti_create_cons_sysfs(struct cti_drvdata *drvdata);
> > +void cti_destroy_cons_sysfs(struct cti_device *ctidev);
> >  struct coresight_platform_data *
> >  coresight_cti_get_platform_data(struct device *dev);
> >
> > --
> > 2.17.1
> >

Thanks

Mike

-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 09/14] coresight: cti: Add connection information to sysfs
  2019-12-02  9:47   ` Suzuki Kuruppassery Poulose
@ 2019-12-06 16:24     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-12-06 16:24 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Hi suzuki,

On Mon, 2 Dec 2019 at 09:48, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > Dynamically adds sysfs attributes for all connections defined in the CTI.
> >
> > Each connection has a triggers<N> sub-directory with name, in_signals,
> > in_types, out_signals and out_types as read-only parameters in the
> > directory. in_ or out_ parameters may be omitted if there are no in or
> > out signals for the connection.
> >
> > Additionally each device has a nr_cons in the connections sub-directory.
> >
> > This allows clients to explore the connection and trigger signal details
> > without needing to refer to device tree or specification of the device.
> >
> > Standardised type information is provided for certain common functions -
> > e.g. snk_full for a trigger from a sink indicating full. Otherwise type
> > defaults to genio.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >   .../hwtracing/coresight/coresight-cti-sysfs.c | 376 +++++++++++++++++-
> >   drivers/hwtracing/coresight/coresight-cti.c   |  13 +-
> >   drivers/hwtracing/coresight/coresight-cti.h   |  11 +-
> >   3 files changed, 396 insertions(+), 4 deletions(-)
> >
>
>
> The patch looks good overall, some minor comments below.
>
>
> > diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > index f800402f73da..91986732506f 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
> > @@ -8,6 +8,67 @@
>
>
> > @@ -818,7 +890,306 @@ static struct attribute *coresight_cti_channel_attrs[] = {
> >       NULL,
> >   };
> >
> > -/* sysfs groups */
> > +/* Create the connections trigger groups and attrs dynamically */
> > +/*
> > + * Each connection has dynamic group triggers<N> + name, trigin/out sigs/types
> > + * attributes, + each device has static nr_trigger_cons giving the number
> > + * of groups. e.g. in sysfs:-
> > + * /cti_<name>/triggers0
> > + * /cti_<name>/triggers1
> > + * /cti_<name>/nr_trigger_cons
> > + * where nr_trigger_cons = 2
> > + */
> > +static ssize_t con_name_show(struct device *dev,
> > +                          struct device_attribute *attr,
> > +                          char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +
> > +     return scnprintf(buf, PAGE_SIZE, "%s\n", con->con_dev_name);
> > +}
> > +
> > +static ssize_t trigin_sig_show(struct device *dev,
> > +                            struct device_attribute *attr,
> > +                            char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +     struct cti_config *cfg = &drvdata->config;
> > +     unsigned long mask = con->con_in->used_mask;
> > +
> > +     return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
> > +}
> > +
> > +static ssize_t trigout_sig_show(struct device *dev,
> > +                             struct device_attribute *attr,
> > +                             char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +     struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > +     struct cti_config *cfg = &drvdata->config;
> > +     unsigned long mask = con->con_out->used_mask;
> > +
> > +     return bitmap_print_to_pagebuf(true, buf, &mask, cfg->nr_trig_max);
> > +}
> > +
> > +/* convert a sig type id to a name */
> > +static const char *
> > +cti_sig_type_name(struct cti_trig_con *con, int used_count, bool in)
> > +{
> > +     int idx = 0;
> > +     struct cti_trig_grp *grp = in ? con->con_in : con->con_out;
> > +
> > +     if (grp->sig_types) {
> > +             if (used_count < grp->nr_sigs)
> > +                     idx = grp->sig_types[used_count];
> > +     }
> > +     return sig_type_names[idx];
> > +}
> > +
> > +static ssize_t trigin_type_show(struct device *dev,
> > +                             struct device_attribute *attr,
> > +                             char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +     int sig_idx, used = 0, b_sz = PAGE_SIZE;
> > +     const char *name;
> > +
> > +     for (sig_idx = 0; sig_idx < con->con_in->nr_sigs; sig_idx++) {
> > +             name = cti_sig_type_name(con, sig_idx, true);
> > +             used += scnprintf(buf + used, b_sz - used, "%s ", name);
> > +     }
> > +     used += scnprintf(buf + used, b_sz - used, "\n");
> > +     return used;
> > +}
> > +
> > +static ssize_t trigout_type_show(struct device *dev,
> > +                              struct device_attribute *attr,
> > +                              char *buf)
> > +{
> > +     struct dev_ext_attribute *ext_attr =
> > +             container_of(attr, struct dev_ext_attribute, attr);
> > +     struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
> > +     int sig_idx, used = 0, b_sz = PAGE_SIZE;
> > +     const char *name;
> > +
> > +     for (sig_idx = 0; sig_idx < con->con_out->nr_sigs; sig_idx++) {
> > +             name = cti_sig_type_name(con, sig_idx, false);
> > +             used += scnprintf(buf + used, b_sz - used, "%s ", name);
> > +     }
> > +     used += scnprintf(buf + used, b_sz - used, "\n");
> > +     return used;
> > +}
> > +
> > +/*
> > + * Array of show function names declared above to allow selection
> > + * for the connection attributes
> > + */
> > +static p_show_fn show_fns[CTI_CON_ATTR_MAX] = {
> > +     con_name_show,
> > +     trigin_sig_show,
> > +     trigout_sig_show,
> > +     trigin_type_show,
> > +     trigout_type_show,
> > +};
> > +
> > +static int cti_create_con_sysfs_attr(struct cti_trig_con *con,
> > +                                  enum cti_conn_attr_type attr_type,
> > +                                  int attr_idx)
> > +{
> > +     struct dev_ext_attribute *dev_ext_attr = 0;
>
> super minor nit: You may use "eattr" instead.
>
>
> > +     char *name = 0;
> > +
> > +     dev_ext_attr = kzalloc(sizeof(struct dev_ext_attribute), GFP_KERNEL);
>
>
> Could we not use devm_* alloc helpers everywhere ?

Yes - will change.

>
> > +     if (dev_ext_attr) {
> > +             name = kstrdup(con_attr_names[attr_type], GFP_KERNEL);
> > +             if (name) {
> > +                     /* fill out the underlying attribute struct */
> > +                     dev_ext_attr->attr.attr.name = name;
> > +                     dev_ext_attr->attr.attr.mode = 0444;
> > +
> > +                     /* now the device_attribute struct */
> > +                     dev_ext_attr->attr.show = show_fns[attr_type];
> > +             } else {
> > +                     kfree(dev_ext_attr);
> > +                     return -ENOMEM;
> > +             }
> > +     } else {
> > +             return -ENOMEM;
> > +     }
> > +     dev_ext_attr->var = con;
> > +     con->con_attrs[attr_idx] = &dev_ext_attr->attr.attr;
> > +     return 0;
> > +}
> > +
> > +static struct attribute_group *
> > +cti_create_con_sysfs_group(struct cti_device *ctidev, int con_idx,
> > +                        struct cti_trig_con *con)
> > +{
> > +     struct attribute_group *group = NULL;
> > +
> > +     group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
> > +     if (!group)
> > +             return NULL;
> > +
> > +     group->name = kasprintf(GFP_KERNEL, "triggers%d", con_idx);
> > +     if (!group->name) {
> > +             kfree(group);
> > +             return NULL;
> > +     }
> > +
> > +     ctidev->con_groups[con_idx + CORESIGHT_CTI_STATIC_GROUPS_MAX - 1]
> > +             = group;
>
> nit:
>         con_idx +=  CORESIGHT_CTI_STATIC_GROUPS_MAX - 1;
>         ctidev->con_groups[con_idx] = group;
>
OK.
>
> > +     con->attr_group = group;
> > +     return group;
> > +}
> > +
> > +/* create a triggers connection group and the attributes for that group */
> > +static int cti_create_con_attr_set(int con_idx, struct cti_device *ctidev,
> > +                                struct cti_trig_con *con)
> > +{
> > +     struct attribute_group *attr_group = NULL;
> > +     int attr_idx = 0;
> > +     int err = -ENOMEM;
> > +
> > +     attr_group = cti_create_con_sysfs_group(ctidev, con_idx, con);
> > +     if (!attr_group)
> > +             return -ENOMEM;
> > +
> > +     /* allocate NULL terminated array of attributes */
> > +     con->con_attrs = kcalloc(CTI_CON_ATTR_MAX + 1,
> > +                              sizeof(struct attribute *),
> > +                              GFP_KERNEL);
>
> Again why not devm_* allocations ? That takes the pain of freeing the
> memory away and helps prevent memory leaks.
>
> > +     if (!con->con_attrs)
> > +             return -ENOMEM;
> > +
> > +     err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_NAME, attr_idx++);
> > +     if (err)
> > +             return err;
> > +
> > +     if (con->con_in->nr_sigs > 0) {
> > +             err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_SIG,
> > +                                             attr_idx++);
> > +             if (err)
> > +                     return err;
> > +
> > +             err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGIN_TYPES,
> > +                                             attr_idx++);
> > +             if (err)
> > +                     return err;
> > +     }
> > +
> > +     if (con->con_in->nr_sigs > 0) {
> > +             err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_SIG,
> > +                                             attr_idx++);
> > +             if (err)
> > +                     return err;
> > +
> > +             err = cti_create_con_sysfs_attr(con, CTI_CON_ATTR_TRIGOUT_TYPES,
> > +                                             attr_idx++);
> > +             if (err)
> > +                     return err;
> > +     }
> > +     attr_group->attrs = con->con_attrs;
> > +     return 0;
> > +}
> > +
> > +/* create the array of group pointers for the CTI sysfs groups */
> > +int cti_create_cons_groups(struct cti_device *ctidev)
> > +{
> > +     int i, nr_groups;
> > +
> > +     /* nr groups - dynamic + static + NULL terminator */
> > +     nr_groups = ctidev->nr_trig_con + CORESIGHT_CTI_STATIC_GROUPS_MAX;
> > +     ctidev->con_groups = kcalloc(nr_groups,
> > +                                  sizeof(struct attribute_group *),
> > +                                  GFP_KERNEL);
> > +     if (!ctidev->con_groups)
> > +             return -ENOMEM;
> > +
> > +     /* populate first locations with the static set of groups */
> > +     for (i = 0; i < (CORESIGHT_CTI_STATIC_GROUPS_MAX - 1); i++)
> > +             ctidev->con_groups[i] = coresight_cti_groups[i];
> > +
> > +     return 0;
> > +}
> > +
>
> To be frank, it doesn't make sense to have this split of populating
> the groups.
Moved to caller.

>
> > +int cti_create_cons_sysfs(struct cti_drvdata *drvdata)
> > +{
> > +     struct cti_device *ctidev = &drvdata->ctidev;
> > +     int err, con_idx = 0;
> > +     struct cti_trig_con *tc = NULL;
> > +
> > +     err = cti_create_cons_groups(ctidev);
> > +     if (err)
> > +             return err;
> > +
> > +     /* add dynamic set for each connection */
> > +     list_for_each_entry(tc, &ctidev->trig_cons, node) {
> > +             err = cti_create_con_attr_set(con_idx++, ctidev, tc);
> > +             if (err)
> > +                     goto cons_sysfs_err;
> > +     }
> > +     return 0;
> > +
> > +cons_sysfs_err:
> > +     cti_destroy_cons_sysfs(ctidev);
> > +     return err;
> > +}
> > +
> > +void cti_free_con_attr(struct attribute *con_attr)
> > +{
> > +     struct device_attribute *dattr =
> > +             container_of(con_attr, struct device_attribute, attr);
> > +     struct dev_ext_attribute *dev_ext_attr =
> > +             container_of(dattr, struct dev_ext_attribute, attr);
> > +     kfree(con_attr->name);
> > +     kfree(dev_ext_attr);
> > +}
> > +
> > +void cti_free_con_group(struct attribute_group *attr_group)
> > +{
> > +     if (attr_group) {
> > +             kfree(attr_group->name);
> > +             kfree(attr_group);
> > +     }
> > +}
> > +
> > +void cti_destroy_cons_attr_set(int con_idx, struct cti_device *ctidev,
> > +                            struct cti_trig_con *con)
> > +{
> > +     int i;
> > +
> > +     if (con->con_attrs) {
> > +             for (i = 0; i < CTI_CON_ATTR_MAX; i++) {
> > +                     if (con->con_attrs[i])
> > +                             cti_free_con_attr(con->con_attrs[i]);
> > +             }
> > +             kfree(con->con_attrs);
> > +     }
> > +     cti_free_con_group(con->attr_group);
> > +}
> > +
> > +void cti_destroy_cons_sysfs(struct cti_device *ctidev)
> > +{
> > +     struct cti_trig_con *tc;
>
> minor nit: Please keep the variable name consistent if possible, helps a
> lot with the code following. i.e, tc vs con above in
> cti_destroy_cons_attr_set().

OK
>
> > +     int con_idx = 0;
> > +
> > +     list_for_each_entry(tc, &ctidev->trig_cons, node) {
> > +             cti_destroy_cons_attr_set(con_idx++, ctidev, tc);
> > +     }
> > +     kfree(ctidev->con_groups);
> > +}
> > +
> > +/* attribute and group sysfs tables. */
> >   static const struct attribute_group coresight_cti_group = {
> >       .attrs = coresight_cti_attrs,
> >   };
> > @@ -838,7 +1209,8 @@ static const struct attribute_group coresight_cti_channels_group = {
> >       .name = "channels",
> >   };
> >
> > -const struct attribute_group *coresight_cti_groups[] = {
> > +const struct attribute_group *
> > +coresight_cti_groups[CORESIGHT_CTI_STATIC_GROUPS_MAX] = {
> >       &coresight_cti_group,
> >       &coresight_cti_mgmt_group,
> >       &coresight_cti_regs_group,
> > diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
> > index cf116463149a..c3d63cc53bdd 100644
> > --- a/drivers/hwtracing/coresight/coresight-cti.c
> > +++ b/drivers/hwtracing/coresight/coresight-cti.c
> > @@ -561,6 +561,9 @@ static void cti_device_release(struct device *dev)
> >
> >       mutex_lock(&ect_mutex);
> >
> > +     /* clear the dynamic sysfs associate with connections */
> > +     cti_destroy_cons_sysfs(&drvdata->ctidev);
> > +
> >       /* remove from the list */
> >       list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
> >               if (ect_item == drvdata) {
> > @@ -636,12 +639,20 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
> >               goto err_out;
> >       }
> >
> > +     /* create dynamic attributes for connections */
> > +     ret = cti_create_cons_sysfs(drvdata);
> > +     if (ret) {
> > +             pr_err("%s: create dynamic sysfs entries failed\n",
> > +                    cti_desc.name);
>
> nit: It may be a good idea to include the actual device name (rather
> than just cti_xxx). so may be :
>
>   dev_err(dev, "%s:....", cti_desc.name) ?
>
>
> > +             goto err_out;
> > +     }
>
>
> Except for the devm_ alloc question, rest are fine.
>
> Suzuki

Thanks

Mike

-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v5 13/14] docs: coresight: Update documentation for CoreSight to cover CTI.
  2019-12-02 10:43   ` Suzuki Kuruppassery Poulose
@ 2019-12-06 17:39     ` Mike Leach
  0 siblings, 0 replies; 62+ messages in thread
From: Mike Leach @ 2019-12-06 17:39 UTC (permalink / raw)
  To: Suzuki Kuruppassery Poulose
  Cc: Coresight ML, linux-arm-kernel, devicetree,
	open list:DOCUMENTATION, Mathieu Poirier

Mathieu, Suzuki,

Fixed per you suggestions.

Thanks

Mike

On Mon, 2 Dec 2019 at 10:43, Suzuki Kuruppassery Poulose
<suzuki.poulose@arm.com> wrote:
>
> On 19/11/2019 23:19, Mike Leach wrote:
> > Add new document covering CTI / CTM usage in CoreSight.
> >
> > Add section in coresight.rst introducing CTI and CTM modules with link
> > to new document.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> >   .../trace/coresight/coresight-ect.rst         | 200 ++++++++++++++++++
> >   Documentation/trace/coresight/coresight.rst   |  13 ++
> >   2 files changed, 213 insertions(+)
> >   create mode 100644 Documentation/trace/coresight/coresight-ect.rst
> >
> > diff --git a/Documentation/trace/coresight/coresight-ect.rst b/Documentation/trace/coresight/coresight-ect.rst
> > new file mode 100644
> > index 000000000000..6448cf910f20
> > --- /dev/null
> > +++ b/Documentation/trace/coresight/coresight-ect.rst
> > @@ -0,0 +1,200 @@
> > +=============================================
> > +CoreSight Embedded Cross Trigger (CTI & CTM).
> > +=============================================
> > +
> > +    :Author:   Mike Leach <mike.leach@linaro.org>
> > +    :Date:     November 2019
> > +
>
> ...
>
>
> > +
> > +Channels API Directory
> > +~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +This provides an easy way to attach triggers to channels, without needing
> > +the multiple register operations that are required if manipluating the
> > +'regs' sub-dir elements directly.
> > +
> > +A number of files provide this API::
> > +
> > +   >$ ls ./cti_sys0/channels/
> > +   chan_clear         chan_inuse         chan_xtrigs_view      trigin_detach
> > +   chan_free          chan_pulse         chan_xtrigs_view_sel  trigout_attach
> > +   chan_gate_disable  chan_set           trig_filter_enable    trigout_detach
> > +   chan_gate_enable   chan_xtrigs_reset  trigin_attach         trigout_filtered
> > +
> > +Most access to these elements take the form::
> > +
> > +  echo <chan> [<trigger>] > /<device_path>/<operation>
> > +
> > +where the optional <trigger> is only needed for trigXX_attach | detach
> > +operations.
> > +
> > +e.g.::
> > +
> > +   >$ echo 0 1 > ./cti_sys0/channels/trigout_attach
> > +   >$ echo 0 > ./cti_sys0/channels/chan_set
> > +
> > +Attaches trigout(1) to channel(0), then activates channel(0) generating a
> > +set state on cti_sys0.trigout(1)
> > +
> > +
> > +*API operations*
> > +
> > +   * ``trigin_attach, trigout_attach``: Attach a channel to a trigger signal.
> > +   * ``trigin_detach, trigout_detach``: Detach a channel from a trigger signal.
> > +   * ``chan_set``: Set the channel - the set state will be propogated around
> > +     the CTM to other connected devices.
> > +   * ``chan_clear``: Clear the channel.
> > +   * ``chan_pulse``: Set the channel for a single CoreSight clock cycle.
> > +   * ``chan_gate_enable``: Write operation sets the CTI gate to propagate
> > +     (enable) the channel to other devices. This operation takes a channel
> > +     number. CTI gate is enabled for all channels by default at power up. Read
> > +     to list the currently enabled channels on the gate.
> > +   * ``chan_gate_disable``: Write channel number to disable gate for that
> > +     channel.
> > +   * ``chan_inuse``: Show the current channels attached to any signal
> > +   * ``chan_free``: Show channels with no attached signals.
> > +   * ``chan_xtrig_view``: write a channel number to select a channel to view,
> > +     read to show the cross triggers programmed for the selected channel.
> > +   * ``trig_filter_enable``: Defaults to enabled, disable to allow potentially
> > +     dangerous output signals to be set.
> > +   * ``trigout_filtered``: Trigger out signals that are prevented from being
> > +     set if filtering ``trig_filter_enable`` is enabled. One use is to prevent
> > +     accidental ``EDBGREQ`` signals stopping a core.
> > +   * ``chan_xtrigs_reset``: Write 1 to clear all channel / trigger programming.
> > +     Resets device hardware to default state.
> > +
> > +e.g.::
> > +
> > +   .../cti_sys0/channels# echo 2 1 > trigin_attach
> > +   .../cti_sys0/channels# echo 2 6 > trigout_attach
>
> minor nit: It may be a good idea to add a comment to describe what you
> are doing with the above operations, to avoid looking up and mapping it
> for someone looking it up. I am not too keen, but it is definitely
> helpful.
>
> > +   .../cti_sys0/channels# cat chan_free
> > +   0-1,3
> > +   .../cti_sys0/channels# cat chan_inuse
> > +   2
> > +   .../cti_sys0/channels# echo 2 > chan_xtrigs_view
> > +   .../cti_sys0/channels# cat chan_xtrigs_view
> > +   [2] IN: 1 OUT: 6
> > +   .../cti_sys0/# echo 1 > enable
> > +   .../cti_sys0/channels# echo 2 > chan_set
> > +   .../cti_sys0/channels# cat ../regs/choutstatus
> > +   0x4
> > +   .../cti_sys0/channels# cat ../regs/trigoutstatus
> > +   0x40
> > +   .../cti_sys0/channels# echo 2 > chan_clear
>
> > +   .../cti_sys0/channels# cat ../regs/trigoutstatus
> > +   0x0
> > +   .../cti_sys0/channels# cat ../regs/trigoutstatus
> > +   0x0
>
> nit: duplicate lines ?
>
> Otherwise:
>
> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>



-- 
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2019-12-06 17:39 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-19 23:18 [PATCH v5 00/14] CoreSight CTI Driver Mike Leach
2019-11-19 23:18 ` [PATCH v5 01/14] coresight: cti: Initial " Mike Leach
2019-11-21 20:21   ` Mathieu Poirier
2019-11-29 12:05     ` Mike Leach
2019-12-03 16:53       ` Mathieu Poirier
2019-11-25 19:03   ` Suzuki Kuruppassery Poulose
2019-11-29 12:06     ` Mike Leach
2019-11-19 23:19 ` [PATCH v5 02/14] coresight: cti: Add sysfs coresight mgmt reg access Mike Leach
2019-11-22 17:19   ` Mathieu Poirier
2019-11-19 23:19 ` [PATCH v5 03/14] coresight: cti: Add sysfs access to program function regs Mike Leach
2019-11-27 18:26   ` Suzuki Kuruppassery Poulose
2019-11-29 12:47     ` Mike Leach
2019-11-28 10:54   ` Suzuki Kuruppassery Poulose
2019-11-28 17:20     ` Mathieu Poirier
2019-11-28 18:00       ` Suzuki Kuruppassery Poulose
2019-11-29 12:50     ` Mike Leach
2019-11-19 23:19 ` [PATCH v5 04/14] coresight: cti: Add sysfs trigger / channel programming API Mike Leach
2019-11-22 18:40   ` Mathieu Poirier
2019-11-27 18:40   ` Suzuki Kuruppassery Poulose
2019-11-29 13:01     ` Mike Leach
2019-11-19 23:19 ` [PATCH v5 05/14] dt-bindings: arm: Adds CoreSight CTI hardware definitions Mike Leach
2019-11-20 19:06   ` Mathieu Poirier
2019-11-20 22:39     ` Mike Leach
2019-11-22 23:33   ` Rob Herring
2019-11-29 13:50     ` Mike Leach
2019-11-29 14:12       ` Suzuki Kuruppassery Poulose
2019-11-28 18:38   ` Suzuki Kuruppassery Poulose
2019-11-29 13:57     ` Mike Leach
2019-11-19 23:19 ` [PATCH v5 06/14] coresight: cti: Add device tree support for v8 arch CTI Mike Leach
2019-11-25 19:00   ` Mathieu Poirier
2019-11-29 11:33   ` Suzuki Kuruppassery Poulose
2019-12-03 10:59     ` Mike Leach
2019-12-03 11:28       ` Suzuki Kuruppassery Poulose
2019-12-03 12:25         ` Mike Leach
2019-11-19 23:19 ` [PATCH v5 07/14] coresight: cti: Add device tree support for custom CTI Mike Leach
2019-11-25 21:22   ` Mathieu Poirier
2019-11-29 14:16     ` Suzuki Kuruppassery Poulose
2019-11-29 21:11       ` Mathieu Poirier
2019-11-29 14:18   ` Suzuki Kuruppassery Poulose
2019-12-03 14:05     ` Mike Leach
2019-11-19 23:19 ` [PATCH v5 08/14] coresight: cti: Enable CTI associated with devices Mike Leach
2019-11-25 22:45   ` Mathieu Poirier
2019-12-05 16:33     ` Mike Leach
2019-11-29 18:28   ` Suzuki Kuruppassery Poulose
2019-11-29 21:25     ` Mathieu Poirier
2019-12-05 16:33     ` Mike Leach
2019-11-19 23:19 ` [PATCH v5 09/14] coresight: cti: Add connection information to sysfs Mike Leach
2019-11-27 18:09   ` Mathieu Poirier
2019-12-06 16:24     ` Mike Leach
2019-12-02  9:47   ` Suzuki Kuruppassery Poulose
2019-12-06 16:24     ` Mike Leach
2019-11-19 23:19 ` [PATCH v5 10/14] dt-bindings: qcom: Add CTI options for qcom msm8916 Mike Leach
2019-11-27 18:18   ` Mathieu Poirier
2019-11-19 23:19 ` [PATCH v5 11/14] dt-bindings: arm: Juno platform - add CTI entries to device tree Mike Leach
2019-11-27 18:25   ` Mathieu Poirier
2019-11-19 23:19 ` [PATCH v5 12/14] dt-bindings: hisilicon: Add CTI bindings for hi-6220 Mike Leach
2019-11-19 23:19 ` [PATCH v5 13/14] docs: coresight: Update documentation for CoreSight to cover CTI Mike Leach
2019-11-27 19:00   ` Mathieu Poirier
2019-12-02 10:43   ` Suzuki Kuruppassery Poulose
2019-12-06 17:39     ` Mike Leach
2019-11-19 23:19 ` [PATCH v5 14/14] docs: sysfs: coresight: Add sysfs ABI documentation for CTI Mike Leach
2019-11-27 19:08   ` Mathieu Poirier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).