Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1385379 > unrolled thread
| Started by | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| First post | 2016-04-22 19:20 +0200 |
| Last post | 2016-04-22 19:20 +0200 |
| Articles | 18 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH V3 00/18] coresight: tmc: make driver usable by Perf Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
[PATCH V3 06/18] coresight: tmc: cleaning up header file Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
[PATCH V3 18/18] coresight: configuring ETF in FIFO mode when acting as link Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
[PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-25 16:40 +0200
Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-25 16:50 +0200
Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-25 17:00 +0200
Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-25 17:10 +0200
Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-25 17:20 +0200
Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-26 11:30 +0200
Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-25 17:20 +0200
[PATCH V3 01/18] coresight: tmc: modifying naming convention Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
[PATCH V3 02/18] coresight: tmc: waiting for TMCReady bit before programming Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
[PATCH V3 04/18] coresight: tmc: clearly define number of transfers per burst Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
[PATCH V3 07/18] coresight: tmc: splitting driver in ETB/ETF and ETR components Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
[PATCH V3 03/18] coresight: tmc: re-implementing tmc_read_prepare/unprepare() functions Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
[PATCH V3 15/18] coresight: moving struct cs_buffers to header file Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
[PATCH V3 05/18] coresight: tmc: introducing new header file Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-22 19:20 +0200
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 00/18] coresight: tmc: make driver usable by Perf |
| Message-ID | <rqMUh-5Du-3@gated-at.bofh.it> |
This patchset makes the TMC driver usable from Perf by way of the recently added AUX area functionality. Note that only the kernel side of the operation is presented here. The user space perf tool enhancement are kept here[1]. Upstreaming of that portion will follow when the kernel side has been addressed. The first 15 patches remodel the driver so that the functionality is compartmented enough to be used as building blocks when interfacing with the Perf subsystem. Patch 16 and 17 implement the AUX area API, taking heavily on the existing ETB10 implementation. Finally patch 18 allows the TMC to be used as a link rather than a sink, something that is required when dealing with an ETF component. Best regards, Mathieu [1]. https://git.linaro.org/people/mathieu.poirier/coresight.git/shortlog/refs/heads/perf-opencsd-4.6-rc2 Changes for V3: - Reworked drvdata::memwidth assignment. - cleaned up coresight-tmc.h header file. - Added WARN_ON[_ONCE]() on error paths. - Added missing spinlock release. - Using a type 'long' when dealing with local_[cmp]xchg() - Added Suzuki K Poulose's Reviewed-by. Changes for V2: - Renamed functions tmc_read_prepare/unprepare_etf() to tmc_read_prepare/unprepare_etb(). - Consolidated return points in functions tmc_enable_etf/etr_sink(). - Re-wrote allocation schemed in functions tmc_enable_etf/etr_sink(). - Fixed description typos in patch 7/15. - Fixed problem with linksink devices when disabling a path in patch 15/15. Mathieu Poirier (18): coresight: tmc: modifying naming convention coresight: tmc: waiting for TMCReady bit before programming coresight: tmc: re-implementing tmc_read_prepare/unprepare() functions coresight: tmc: clearly define number of transfers per burst coresight: tmc: introducing new header file coresight: tmc: cleaning up header file coresight: tmc: splitting driver in ETB/ETF and ETR components coresight: tmc: making prepare/unprepare functions generic coresight: tmc: allocating memory when needed coresight: tmc: getting the right read_count on tmc_open() coresight: tmc: adding mode of operation for link/sinks coresight: tmc: dump system memory content only when needed coresight: tmc: make sysFS and Perf mode mutually exclusive coresight: tmc: keep track of memory width coresight: moving struct cs_buffers to header file coresight: tmc: implementing TMC-ETF AUX space API coresight: tmc: implementing TMC-ETR AUX space API coresight: configuring ETF in FIFO mode when acting as link drivers/hwtracing/coresight/Makefile | 4 +- drivers/hwtracing/coresight/coresight-etb10.c | 20 - drivers/hwtracing/coresight/coresight-priv.h | 20 + drivers/hwtracing/coresight/coresight-tmc-etf.c | 603 ++++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tmc-etr.c | 469 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-tmc.c | 485 +++---------------- drivers/hwtracing/coresight/coresight-tmc.h | 145 ++++++ drivers/hwtracing/coresight/coresight.c | 32 +- 8 files changed, 1339 insertions(+), 439 deletions(-) create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etf.c create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etr.c create mode 100644 drivers/hwtracing/coresight/coresight-tmc.h -- 2.5.0
[toc] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 06/18] coresight: tmc: cleaning up header file |
| Message-ID | <rqMUi-5Du-21@gated-at.bofh.it> |
| In reply to | #1385379 |
This patch first move the TMC_STS_TMCREADY_BIT and
TMC_FFCR_FLUSHMAN_BIT defines to their respective section.
It also removes TMC_FFCR_FLUSHMAN, since the same result
can easily be obtained using the BIT() macro.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc.c | 2 +-
drivers/hwtracing/coresight/coresight-tmc.h | 5 ++---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index f9a6624ab531..07e2809d832b 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -50,7 +50,7 @@ static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
ffcr |= TMC_FFCR_STOP_ON_FLUSH;
writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
- ffcr |= TMC_FFCR_FLUSHMAN;
+ ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT);
writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
/* Ensure flush completes */
if (coresight_timeout(drvdata->base,
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 49718b4a9788..5a60830c8db5 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -49,6 +49,7 @@
/* TMC_CTL - 0x020 */
#define TMC_CTL_CAPT_EN BIT(0)
/* TMC_STS - 0x00C */
+#define TMC_STS_TMCREADY_BIT 2
#define TMC_STS_TRIGGERED BIT(1)
/* TMC_AXICTL - 0x110 */
#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
@@ -56,16 +57,14 @@
#define TMC_AXICTL_SCT_GAT_MODE BIT(7)
#define TMC_AXICTL_WR_BURST_16 0xF00
/* TMC_FFCR - 0x304 */
+#define TMC_FFCR_FLUSHMAN_BIT 6
#define TMC_FFCR_EN_FMT BIT(0)
#define TMC_FFCR_EN_TI BIT(1)
#define TMC_FFCR_FON_FLIN BIT(4)
#define TMC_FFCR_FON_TRIG_EVT BIT(5)
-#define TMC_FFCR_FLUSHMAN BIT(6)
#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
-#define TMC_STS_TMCREADY_BIT 2
-#define TMC_FFCR_FLUSHMAN_BIT 6
enum tmc_config_type {
TMC_CONFIG_TYPE_ETB,
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 18/18] coresight: configuring ETF in FIFO mode when acting as link |
| Message-ID | <rqMUj-5Du-35@gated-at.bofh.it> |
| In reply to | #1385379 |
When part of a path but not identified as a sink, the EFT has to
be configured as a link and placed in HW FIFO mode. As such when
enabling a path, call the right configuration function based on
the role the ETF if playing in this trace run.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight.c | 32 ++++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 2ea5961092c1..bba9f3d653c9 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -257,15 +257,27 @@ static void coresight_disable_source(struct coresight_device *csdev)
void coresight_disable_path(struct list_head *path)
{
+ u32 type;
struct coresight_node *nd;
struct coresight_device *csdev, *parent, *child;
list_for_each_entry(nd, path, link) {
csdev = nd->csdev;
+ type = csdev->type;
- switch (csdev->type) {
+ /*
+ * ETF devices are tricky... They can be a link or a sink,
+ * depending on how they are configured. If an ETF has been
+ * "activated" it will be configured as a sink, otherwise
+ * go ahead with the link configuration.
+ */
+ if (type == CORESIGHT_DEV_TYPE_LINKSINK)
+ type = (csdev == coresight_get_sink(path)) ?
+ CORESIGHT_DEV_TYPE_SINK :
+ CORESIGHT_DEV_TYPE_LINK;
+
+ switch (type) {
case CORESIGHT_DEV_TYPE_SINK:
- case CORESIGHT_DEV_TYPE_LINKSINK:
coresight_disable_sink(csdev);
break;
case CORESIGHT_DEV_TYPE_SOURCE:
@@ -286,15 +298,27 @@ int coresight_enable_path(struct list_head *path, u32 mode)
{
int ret = 0;
+ u32 type;
struct coresight_node *nd;
struct coresight_device *csdev, *parent, *child;
list_for_each_entry_reverse(nd, path, link) {
csdev = nd->csdev;
+ type = csdev->type;
+
+ /*
+ * ETF devices are tricky... They can be a link or a sink,
+ * depending on how they are configured. If an ETF has been
+ * "activated" it will be configured as a sink, otherwise
+ * go ahead with the link configuration.
+ */
+ if (type == CORESIGHT_DEV_TYPE_LINKSINK)
+ type = (csdev == coresight_get_sink(path)) ?
+ CORESIGHT_DEV_TYPE_SINK :
+ CORESIGHT_DEV_TYPE_LINK;
- switch (csdev->type) {
+ switch (type) {
case CORESIGHT_DEV_TYPE_SINK:
- case CORESIGHT_DEV_TYPE_LINKSINK:
ret = coresight_enable_sink(csdev, mode);
if (ret)
goto err;
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive |
| Message-ID | <rqMUj-5Du-29@gated-at.bofh.it> |
| In reply to | #1385379 |
The sysFS and Perf access methods can't be allowed to interfere
with one another. As such introducing guards to access
functions that prevents moving forward if a TMC is already
being used.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight-tmc-etf.c | 60 +++++++++++++++++++++-
drivers/hwtracing/coresight/coresight-tmc-etr.c | 68 +++++++++++++++++++++++--
2 files changed, 121 insertions(+), 7 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 25fad93b68d4..cc88c15ba45c 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -111,7 +111,7 @@ static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
CS_LOCK(drvdata->base);
}
-static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
{
bool used = false;
char *buf = NULL;
@@ -190,6 +190,54 @@ spin_unlock:
return 0;
}
+static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
+{
+ int ret = 0;
+ long val;
+ unsigned long flags;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ /* This shouldn't be happening */
+ if (WARN_ON(mode != CS_MODE_PERF))
+ return -EINVAL;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ val = local_xchg(&drvdata->mode, mode);
+ /*
+ * In Perf mode there can be only one writer per sink. There
+ * is also no need to continue if the ETB/ETR is already operated
+ * from sysFS.
+ */
+ if (val != CS_MODE_DISABLED) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tmc_etb_enable_hw(drvdata);
+out:
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ return ret;
+}
+
+static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
+{
+ switch (mode) {
+ case CS_MODE_SYSFS:
+ return tmc_enable_etf_sink_sysfs(csdev, mode);
+ case CS_MODE_PERF:
+ return tmc_enable_etf_sink_perf(csdev, mode);
+ }
+
+ /* We shouldn't be here */
+ return -EINVAL;
+}
+
static void tmc_disable_etf_sink(struct coresight_device *csdev)
{
long val;
@@ -272,6 +320,7 @@ const struct coresight_ops tmc_etf_cs_ops = {
int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
{
+ long val;
enum tmc_mode mode;
int ret = 0;
unsigned long flags;
@@ -290,6 +339,13 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
goto out;
}
+ val = local_read(&drvdata->mode);
+ /* Don't interfere if operated from Perf */
+ if (val == CS_MODE_PERF) {
+ ret = -EINVAL;
+ goto out;
+ }
+
/* If drvdata::buf is NULL the trace data has been read already */
if (drvdata->buf == NULL) {
ret = -EINVAL;
@@ -297,7 +353,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
}
/* Disable the TMC if need be */
- if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+ if (val == CS_MODE_SYSFS)
tmc_etb_disable_hw(drvdata);
drvdata->reading = true;
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 4b000f4003a2..a9a94a09186a 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -87,7 +87,7 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
CS_LOCK(drvdata->base);
}
-static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
{
bool used = false;
long val;
@@ -167,6 +167,54 @@ spin_unlock:
return 0;
}
+static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
+{
+ int ret = 0;
+ long val;
+ unsigned long flags;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ /* This shouldn't be happening */
+ if (WARN_ON(mode != CS_MODE_PERF))
+ return -EINVAL;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ val = local_xchg(&drvdata->mode, mode);
+ /*
+ * In Perf mode there can be only one writer per sink. There
+ * is also no need to continue if the ETR is already operated
+ * from sysFS.
+ */
+ if (val != CS_MODE_DISABLED) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tmc_etr_enable_hw(drvdata);
+out:
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ return ret;
+}
+
+static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
+{
+ switch (mode) {
+ case CS_MODE_SYSFS:
+ return tmc_enable_etr_sink_sysfs(csdev, mode);
+ case CS_MODE_PERF:
+ return tmc_enable_etr_sink_perf(csdev, mode);
+ }
+
+ /* We shouldn't be here */
+ return -EINVAL;
+}
+
static void tmc_disable_etr_sink(struct coresight_device *csdev)
{
long val;
@@ -200,6 +248,8 @@ const struct coresight_ops tmc_etr_cs_ops = {
int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
{
+ int ret = 0;
+ long val;
unsigned long flags;
/* config types are set a boot time and never change */
@@ -208,20 +258,28 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
spin_lock_irqsave(&drvdata->spinlock, flags);
+ val = local_read(&drvdata->mode);
+ /* Don't interfere if operated from Perf */
+ if (val == CS_MODE_PERF) {
+ ret = -EINVAL;
+ goto out;
+ }
+
/* If drvdata::buf is NULL the trace data has been read already */
if (drvdata->buf == NULL) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
/* Disable the TMC if need be */
- if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+ if (val == CS_MODE_SYSFS)
tmc_etr_disable_hw(drvdata);
drvdata->reading = true;
+out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return 0;
+ return ret;
}
int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-04-25 16:40 +0200 |
| Subject | Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive |
| Message-ID | <rrPQ8-7se-63@gated-at.bofh.it> |
| In reply to | #1385382 |
On 22/04/16 18:14, Mathieu Poirier wrote:
> The sysFS and Perf access methods can't be allowed to interfere
> with one another. As such introducing guards to access
> functions that prevents moving forward if a TMC is already
> being used.
>
> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> ---
> drivers/hwtracing/coresight/coresight-tmc-etf.c | 60 +++++++++++++++++++++-
> drivers/hwtracing/coresight/coresight-tmc-etr.c | 68 +++++++++++++++++++++++--
> 2 files changed, 121 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> index 25fad93b68d4..cc88c15ba45c 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> @@ -111,7 +111,7 @@ static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
> CS_LOCK(drvdata->base);
> }
>
> -static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
> +static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
> {
> bool used = false;
> char *buf = NULL;
> @@ -190,6 +190,54 @@ spin_unlock:
> return 0;
> }
>
> +static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
> +{
> + int ret = 0;
> + long val;
> + unsigned long flags;
> + struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> + /* This shouldn't be happening */
> + if (WARN_ON(mode != CS_MODE_PERF))
> + return -EINVAL;
> +
> + spin_lock_irqsave(&drvdata->spinlock, flags);
> + if (drvdata->reading) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + val = local_xchg(&drvdata->mode, mode);
> + /*
> + * In Perf mode there can be only one writer per sink. There
> + * is also no need to continue if the ETB/ETR is already operated
> + * from sysFS.
> + */
> + if (val != CS_MODE_DISABLED) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + tmc_etb_enable_hw(drvdata);
> +out:
> + spin_unlock_irqrestore(&drvdata->spinlock, flags);
> +
> + return ret;
> +}
> +
> +static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
> +{
> + switch (mode) {
> + case CS_MODE_SYSFS:
> + return tmc_enable_etf_sink_sysfs(csdev, mode);
> + case CS_MODE_PERF:
> + return tmc_enable_etf_sink_perf(csdev, mode);
> + }
> +
> + /* We shouldn't be here */
> + return -EINVAL;
> +}
> +
> static void tmc_disable_etf_sink(struct coresight_device *csdev)
> {
> long val;
> @@ -272,6 +320,7 @@ const struct coresight_ops tmc_etf_cs_ops = {
>
> int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
> {
> + long val;
> enum tmc_mode mode;
> int ret = 0;
> unsigned long flags;
> @@ -290,6 +339,13 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
> goto out;
> }
>
> + val = local_read(&drvdata->mode);
> + /* Don't interfere if operated from Perf */
> + if (val == CS_MODE_PERF) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> /* If drvdata::buf is NULL the trace data has been read already */
> if (drvdata->buf == NULL) {
> ret = -EINVAL;
> @@ -297,7 +353,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
> }
>
> /* Disable the TMC if need be */
> - if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
> + if (val == CS_MODE_SYSFS)
> tmc_etb_disable_hw(drvdata);
>
> drvdata->reading = true;
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> index 4b000f4003a2..a9a94a09186a 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
> @@ -87,7 +87,7 @@ static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
> CS_LOCK(drvdata->base);
> }
>
> -static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
> +static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
> {
> bool used = false;
> long val;
> @@ -167,6 +167,54 @@ spin_unlock:
> return 0;
> }
>
> +static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
> +{
> + int ret = 0;
> + long val;
> + unsigned long flags;
> + struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> +
> + /* This shouldn't be happening */
> + if (WARN_ON(mode != CS_MODE_PERF))
> + return -EINVAL;
> +
> + spin_lock_irqsave(&drvdata->spinlock, flags);
> + if (drvdata->reading) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + val = local_xchg(&drvdata->mode, mode);
> + /*
> + * In Perf mode there can be only one writer per sink. There
> + * is also no need to continue if the ETR is already operated
> + * from sysFS.
> + */
> + if (val != CS_MODE_DISABLED) {
Could val be CS_MODE_PERF ? In other words, should we be checking :
if (val == CS_MODE_SYSFS) instead ?
Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-25 16:50 +0200 |
| Subject | Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive |
| Message-ID | <rrPZL-7wH-3@gated-at.bofh.it> |
| In reply to | #1386544 |
On 25 April 2016 at 08:32, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
> On 22/04/16 18:14, Mathieu Poirier wrote:
>>
>> The sysFS and Perf access methods can't be allowed to interfere
>> with one another. As such introducing guards to access
>> functions that prevents moving forward if a TMC is already
>> being used.
>>
>> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>> ---
>> drivers/hwtracing/coresight/coresight-tmc-etf.c | 60
>> +++++++++++++++++++++-
>> drivers/hwtracing/coresight/coresight-tmc-etr.c | 68
>> +++++++++++++++++++++++--
>> 2 files changed, 121 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> b/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> index 25fad93b68d4..cc88c15ba45c 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> @@ -111,7 +111,7 @@ static void tmc_etf_disable_hw(struct tmc_drvdata
>> *drvdata)
>> CS_LOCK(drvdata->base);
>> }
>>
>> -static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
>> +static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32
>> mode)
>> {
>> bool used = false;
>> char *buf = NULL;
>> @@ -190,6 +190,54 @@ spin_unlock:
>> return 0;
>> }
>>
>> +static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32
>> mode)
>> +{
>> + int ret = 0;
>> + long val;
>> + unsigned long flags;
>> + struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> + /* This shouldn't be happening */
>> + if (WARN_ON(mode != CS_MODE_PERF))
>> + return -EINVAL;
>> +
>> + spin_lock_irqsave(&drvdata->spinlock, flags);
>> + if (drvdata->reading) {
>> + ret = -EINVAL;
>> + goto out;
>> + }
>> +
>> + val = local_xchg(&drvdata->mode, mode);
>> + /*
>> + * In Perf mode there can be only one writer per sink. There
>> + * is also no need to continue if the ETB/ETR is already operated
>> + * from sysFS.
>> + */
>> + if (val != CS_MODE_DISABLED) {
>> + ret = -EINVAL;
>> + goto out;
>> + }
>> +
>> + tmc_etb_enable_hw(drvdata);
>> +out:
>> + spin_unlock_irqrestore(&drvdata->spinlock, flags);
>> +
>> + return ret;
>> +}
>> +
>> +static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
>> +{
>> + switch (mode) {
>> + case CS_MODE_SYSFS:
>> + return tmc_enable_etf_sink_sysfs(csdev, mode);
>> + case CS_MODE_PERF:
>> + return tmc_enable_etf_sink_perf(csdev, mode);
>> + }
>> +
>> + /* We shouldn't be here */
>> + return -EINVAL;
>> +}
>> +
>> static void tmc_disable_etf_sink(struct coresight_device *csdev)
>> {
>> long val;
>> @@ -272,6 +320,7 @@ const struct coresight_ops tmc_etf_cs_ops = {
>>
>> int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
>> {
>> + long val;
>> enum tmc_mode mode;
>> int ret = 0;
>> unsigned long flags;
>> @@ -290,6 +339,13 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
>> goto out;
>> }
>>
>> + val = local_read(&drvdata->mode);
>> + /* Don't interfere if operated from Perf */
>> + if (val == CS_MODE_PERF) {
>> + ret = -EINVAL;
>> + goto out;
>> + }
>> +
>> /* If drvdata::buf is NULL the trace data has been read already */
>> if (drvdata->buf == NULL) {
>> ret = -EINVAL;
>> @@ -297,7 +353,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
>> }
>>
>> /* Disable the TMC if need be */
>> - if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
>> + if (val == CS_MODE_SYSFS)
>> tmc_etb_disable_hw(drvdata);
>>
>> drvdata->reading = true;
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> index 4b000f4003a2..a9a94a09186a 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> @@ -87,7 +87,7 @@ static void tmc_etr_disable_hw(struct tmc_drvdata
>> *drvdata)
>> CS_LOCK(drvdata->base);
>> }
>>
>> -static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
>> +static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32
>> mode)
>> {
>> bool used = false;
>> long val;
>> @@ -167,6 +167,54 @@ spin_unlock:
>> return 0;
>> }
>>
>> +static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32
>> mode)
>> +{
>> + int ret = 0;
>> + long val;
>> + unsigned long flags;
>> + struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> + /* This shouldn't be happening */
>> + if (WARN_ON(mode != CS_MODE_PERF))
>> + return -EINVAL;
>> +
>> + spin_lock_irqsave(&drvdata->spinlock, flags);
>> + if (drvdata->reading) {
>> + ret = -EINVAL;
>> + goto out;
>> + }
>> +
>> + val = local_xchg(&drvdata->mode, mode);
>> + /*
>> + * In Perf mode there can be only one writer per sink. There
>> + * is also no need to continue if the ETR is already operated
>> + * from sysFS.
>> + */
>> + if (val != CS_MODE_DISABLED) {
>
>
> Could val be CS_MODE_PERF ? In other words, should we be checking :
> if (val == CS_MODE_SYSFS) instead ?
If we check for CS_MODE_SYSFS we also have to check for CS_MODE_PERF,
which is two checks rather than a single one with the current
solution.
Mathieu
>
> Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-04-25 17:00 +0200 |
| Subject | Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive |
| Message-ID | <rrQ9s-7Bm-35@gated-at.bofh.it> |
| In reply to | #1386547 |
On 25/04/16 15:48, Mathieu Poirier wrote:
> On 25 April 2016 at 08:32, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
>> On 22/04/16 18:14, Mathieu Poirier wrote:
>>> + spin_lock_irqsave(&drvdata->spinlock, flags);
>>> + if (drvdata->reading) {
>>> + ret = -EINVAL;
>>> + goto out;
>>> + }
>>> +
>>> + val = local_xchg(&drvdata->mode, mode);
>>> + /*
>>> + * In Perf mode there can be only one writer per sink. There
>>> + * is also no need to continue if the ETR is already operated
>>> + * from sysFS.
>>> + */
>>> + if (val != CS_MODE_DISABLED) {
>>
>>
>> Could val be CS_MODE_PERF ? In other words, should we be checking :
>> if (val == CS_MODE_SYSFS) instead ?
>
> If we check for CS_MODE_SYSFS we also have to check for CS_MODE_PERF,
> which is two checks rather than a single one with the current
> solution.
I am confused now. The comment says, we want to check for sysfs mode and
don't continue in that case. So, we shouldn't be worried about PERF mode.
Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-25 17:10 +0200 |
| Subject | Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive |
| Message-ID | <rrQj8-80L-9@gated-at.bofh.it> |
| In reply to | #1386557 |
On 25 April 2016 at 08:52, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
> On 25/04/16 15:48, Mathieu Poirier wrote:
>>
>> On 25 April 2016 at 08:32, Suzuki K Poulose <Suzuki.Poulose@arm.com>
>> wrote:
>>>
>>> On 22/04/16 18:14, Mathieu Poirier wrote:
>
>
>>>> + spin_lock_irqsave(&drvdata->spinlock, flags);
>>>> + if (drvdata->reading) {
>>>> + ret = -EINVAL;
>>>> + goto out;
>>>> + }
>>>> +
>>>> + val = local_xchg(&drvdata->mode, mode);
>>>> + /*
>>>> + * In Perf mode there can be only one writer per sink. There
>>>> + * is also no need to continue if the ETR is already operated
>>>> + * from sysFS.
>>>> + */
>>>> + if (val != CS_MODE_DISABLED) {
>>>
>>>
>>>
>>> Could val be CS_MODE_PERF ? In other words, should we be checking :
>>> if (val == CS_MODE_SYSFS) instead ?
>>
>>
>> If we check for CS_MODE_SYSFS we also have to check for CS_MODE_PERF,
>> which is two checks rather than a single one with the current
>> solution.
>
>
> I am confused now. The comment says, we want to check for sysfs mode and
> don't continue in that case. So, we shouldn't be worried about PERF mode.
You are correct about the sysFS part, but the first sentence of the
comment also mention that in perf mode there can only be one writer
per sink. Otherwise ring buffers for one session would end up with
traces from other ongoing sessions, and that is not taking into
account the buffer management nightmares it would cause.
Mathieu
>
> Suzuki
>
>
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-25 17:20 +0200 |
| Subject | Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive |
| Message-ID | <rrQsN-856-7@gated-at.bofh.it> |
| In reply to | #1386560 |
On 25 April 2016 at 09:11, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
> On 25/04/16 16:05, Mathieu Poirier wrote:
>>
>> On 25 April 2016 at 08:52, Suzuki K Poulose <Suzuki.Poulose@arm.com>
>> wrote:
>>>
>>> On 25/04/16 15:48, Mathieu Poirier wrote:
>>>>
>>>>
>>>> On 25 April 2016 at 08:32, Suzuki K Poulose <Suzuki.Poulose@arm.com>
>>>> wrote:
>>>>>
>>>>>
>>>>> On 22/04/16 18:14, Mathieu Poirier wrote:
>>>
>>>
>>>
>>>>>> + spin_lock_irqsave(&drvdata->spinlock, flags);
>>>>>> + if (drvdata->reading) {
>>>>>> + ret = -EINVAL;
>>>>>> + goto out;
>>>>>> + }
>>>>>> +
>>>>>> + val = local_xchg(&drvdata->mode, mode);
>>>>>> + /*
>>>>>> + * In Perf mode there can be only one writer per sink. There
>>>>>> + * is also no need to continue if the ETR is already operated
>>>>>> + * from sysFS.
>>>>>> + */
>>>>>> + if (val != CS_MODE_DISABLED) {
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Could val be CS_MODE_PERF ? In other words, should we be checking :
>>>>> if (val == CS_MODE_SYSFS) instead ?
>>>>
>>>>
>>>>
>>>> If we check for CS_MODE_SYSFS we also have to check for CS_MODE_PERF,
>>>> which is two checks rather than a single one with the current
>>>> solution.
>>>
>>>
>>>
>>> I am confused now. The comment says, we want to check for sysfs mode and
>>> don't continue in that case. So, we shouldn't be worried about PERF mode.
>>
>>
>> You are correct about the sysFS part, but the first sentence of the
>> comment also mention that in perf mode there can only be one writer
>> per sink. Otherwise ring buffers for one session would end up with
>> traces from other ongoing sessions, and that is not taking into
>> account the buffer management nightmares it would cause.
>
>
> OK, in either case, val == CS_MODE_SYSFS is much better check there, to
> what we want to do
If we check for SYSFS we also need to check for PERF. Otherwise
nothing prevents another session from using the sink buffer, which is
not supported.
>
> Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-04-26 11:30 +0200 |
| Subject | Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive |
| Message-ID | <rs7tE-57R-5@gated-at.bofh.it> |
| In reply to | #1386568 |
On 25/04/16 16:18, Mathieu Poirier wrote:
> On 25 April 2016 at 09:11, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
>> On 25/04/16 16:05, Mathieu Poirier wrote:
>>>
>>> On 25 April 2016 at 08:52, Suzuki K Poulose <Suzuki.Poulose@arm.com>
>>> wrote:
>>>>
>>>> On 25/04/16 15:48, Mathieu Poirier wrote:
>>>>>
>>>>>
>>>>> On 25 April 2016 at 08:32, Suzuki K Poulose <Suzuki.Poulose@arm.com>
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>> On 22/04/16 18:14, Mathieu Poirier wrote:
>>>>
>>>>
>>>>
>>>>>>> + spin_lock_irqsave(&drvdata->spinlock, flags);
>>>>>>> + if (drvdata->reading) {
>>>>>>> + ret = -EINVAL;
>>>>>>> + goto out;
>>>>>>> + }
>>>>>>> +
>>>>>>> + val = local_xchg(&drvdata->mode, mode);
>>>>>>> + /*
>>>>>>> + * In Perf mode there can be only one writer per sink. There
>>>>>>> + * is also no need to continue if the ETR is already operated
>>>>>>> + * from sysFS.
>>>>>>> + */
>>>>>>> + if (val != CS_MODE_DISABLED) {
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Could val be CS_MODE_PERF ? In other words, should we be checking :
>>>>>> if (val == CS_MODE_SYSFS) instead ?
>>>>>
>>>>>
>>>>>
>>>>> If we check for CS_MODE_SYSFS we also have to check for CS_MODE_PERF,
>>>>> which is two checks rather than a single one with the current
>>>>> solution.
>>>>
>>>>
>>>>
>>>> I am confused now. The comment says, we want to check for sysfs mode and
>>>> don't continue in that case. So, we shouldn't be worried about PERF mode.
>>>
>>>
>>> You are correct about the sysFS part, but the first sentence of the
>>> comment also mention that in perf mode there can only be one writer
>>> per sink. Otherwise ring buffers for one session would end up with
>>> traces from other ongoing sessions, and that is not taking into
>>> account the buffer management nightmares it would cause.
>>
>>
>> OK, in either case, val == CS_MODE_SYSFS is much better check there, to
>> what we want to do
>
> If we check for SYSFS we also need to check for PERF. Otherwise
> nothing prevents another session from using the sink buffer, which is
> not supported.
Ah, I got wrong. Sorry for the noise. The current check makes sense.
Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-04-25 17:20 +0200 |
| Subject | Re: [PATCH V3 13/18] coresight: tmc: make sysFS and Perf mode mutually exclusive |
| Message-ID | <rrQsN-856-9@gated-at.bofh.it> |
| In reply to | #1386560 |
On 25/04/16 16:05, Mathieu Poirier wrote:
> On 25 April 2016 at 08:52, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
>> On 25/04/16 15:48, Mathieu Poirier wrote:
>>>
>>> On 25 April 2016 at 08:32, Suzuki K Poulose <Suzuki.Poulose@arm.com>
>>> wrote:
>>>>
>>>> On 22/04/16 18:14, Mathieu Poirier wrote:
>>
>>
>>>>> + spin_lock_irqsave(&drvdata->spinlock, flags);
>>>>> + if (drvdata->reading) {
>>>>> + ret = -EINVAL;
>>>>> + goto out;
>>>>> + }
>>>>> +
>>>>> + val = local_xchg(&drvdata->mode, mode);
>>>>> + /*
>>>>> + * In Perf mode there can be only one writer per sink. There
>>>>> + * is also no need to continue if the ETR is already operated
>>>>> + * from sysFS.
>>>>> + */
>>>>> + if (val != CS_MODE_DISABLED) {
>>>>
>>>>
>>>>
>>>> Could val be CS_MODE_PERF ? In other words, should we be checking :
>>>> if (val == CS_MODE_SYSFS) instead ?
>>>
>>>
>>> If we check for CS_MODE_SYSFS we also have to check for CS_MODE_PERF,
>>> which is two checks rather than a single one with the current
>>> solution.
>>
>>
>> I am confused now. The comment says, we want to check for sysfs mode and
>> don't continue in that case. So, we shouldn't be worried about PERF mode.
>
> You are correct about the sysFS part, but the first sentence of the
> comment also mention that in perf mode there can only be one writer
> per sink. Otherwise ring buffers for one session would end up with
> traces from other ongoing sessions, and that is not taking into
> account the buffer management nightmares it would cause.
OK, in either case, val == CS_MODE_SYSFS is much better check there, to
what we want to do
Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 01/18] coresight: tmc: modifying naming convention |
| Message-ID | <rqMUj-5Du-39@gated-at.bofh.it> |
| In reply to | #1385379 |
According to the TMC architectural state machine, the 'stopped'
state is reached when bit 2 (TMCReady) of the TMC Status register
turns to '1'. The code is correct but the naming convention isn't.
The 'Triggered' bit occupies position '1' of the TMC Status register
and has nothing to do with the indication of the TMC entering the
stopped state. As such renaming function "tmc_wait_for_triggered()"
and changing the #define to reflect what the code is really doing.
This patch has no effect other than clarifying the semantic.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 2b42ecbd8831..3f646e29a99b 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -77,7 +77,7 @@
#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
-#define TMC_STS_TRIGGERED_BIT 2
+#define TMC_STS_TMCREADY_BIT 2
#define TMC_FFCR_FLUSHMAN_BIT 6
enum tmc_config_type {
@@ -132,11 +132,11 @@ struct tmc_drvdata {
u32 trigger_cntr;
};
-static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
+static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
{
/* Ensure formatter, unformatter and hardware fifo are empty */
if (coresight_timeout(drvdata->base,
- TMC_STS, TMC_STS_TRIGGERED_BIT, 1)) {
+ TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
dev_err(drvdata->dev,
"timeout observed when probing at offset %#x\n",
TMC_STS);
@@ -160,7 +160,7 @@ static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
TMC_FFCR);
}
- tmc_wait_for_ready(drvdata);
+ tmc_wait_for_tmcready(drvdata);
}
static void tmc_enable_hw(struct tmc_drvdata *drvdata)
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 02/18] coresight: tmc: waiting for TMCReady bit before programming |
| Message-ID | <rqMUj-5Du-31@gated-at.bofh.it> |
| In reply to | #1385379 |
According to the TRM before programming the TMC in circular
buffer mode (and that for any configuration, ETB, ETR, ETF),
the TMCReady bit in the status register has to be set.
This patch adds a check to make sure the state machine is in
a state where it can be configured, and complains otherwise.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 3f646e29a99b..66fa7736d12f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -180,6 +180,9 @@ static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
CS_UNLOCK(drvdata->base);
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
@@ -201,6 +204,9 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
CS_UNLOCK(drvdata->base);
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
@@ -230,6 +236,9 @@ static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
{
CS_UNLOCK(drvdata->base);
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
drvdata->base + TMC_FFCR);
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 04/18] coresight: tmc: clearly define number of transfers per burst |
| Message-ID | <rqMUj-5Du-37@gated-at.bofh.it> |
| In reply to | #1385379 |
This patch makes the name of the define reflect the amount of data tranfers per burst, in this case 16. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> --- drivers/hwtracing/coresight/coresight-tmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index d211aeec49f8..8751d53fa078 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -67,7 +67,7 @@ #define TMC_AXICTL_PROT_CTL_B0 BIT(0) #define TMC_AXICTL_PROT_CTL_B1 BIT(1) #define TMC_AXICTL_SCT_GAT_MODE BIT(7) -#define TMC_AXICTL_WR_BURST_LEN 0xF00 +#define TMC_AXICTL_WR_BURST_16 0xF00 /* TMC_FFCR - 0x304 */ #define TMC_FFCR_EN_FMT BIT(0) #define TMC_FFCR_EN_TI BIT(1) @@ -211,7 +211,7 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata) writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE); axictl = readl_relaxed(drvdata->base + TMC_AXICTL); - axictl |= TMC_AXICTL_WR_BURST_LEN; + axictl |= TMC_AXICTL_WR_BURST_16; writel_relaxed(axictl, drvdata->base + TMC_AXICTL); axictl &= ~TMC_AXICTL_SCT_GAT_MODE; writel_relaxed(axictl, drvdata->base + TMC_AXICTL); -- 2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 07/18] coresight: tmc: splitting driver in ETB/ETF and ETR components |
| Message-ID | <rqMUj-5Du-43@gated-at.bofh.it> |
| In reply to | #1385379 |
The TMC block can operate in 3 modes (ETB, ETF and ETR) and accessed
via two interfaces (sysFS and Perf). That makes 6 mode to cover, which
is way too much coupling for a single file.
This patch splits the original TMC driver in 2 halves, one for ETB/ETF
and another one for ETR mode. A common core is kept for functionality
common to all 3 modes.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/Makefile | 4 +-
drivers/hwtracing/coresight/coresight-tmc-etf.c | 204 ++++++++++++++++++
drivers/hwtracing/coresight/coresight-tmc-etr.c | 128 ++++++++++++
drivers/hwtracing/coresight/coresight-tmc.c | 264 +-----------------------
drivers/hwtracing/coresight/coresight-tmc.h | 18 ++
5 files changed, 357 insertions(+), 261 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etf.c
create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etr.c
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 1d0e32c7dbe4..0cf842ea3fe2 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -3,7 +3,9 @@
#
obj-$(CONFIG_CORESIGHT) += coresight.o coresight-etm-perf.o
obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
+obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o \
+ coresight-tmc-etf.o \
+ coresight-tmc-etr.o
obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
new file mode 100644
index 000000000000..467d19221f7b
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright(C) 2016 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/coresight.h>
+#include "coresight-priv.h"
+#include "coresight-tmc.h"
+
+void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
+{
+ /* Zero out the memory to help with debug */
+ memset(drvdata->buf, 0, drvdata->size);
+
+ CS_UNLOCK(drvdata->base);
+
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
+ writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+ writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+ TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+ TMC_FFCR_TRIGON_TRIGIN,
+ drvdata->base + TMC_FFCR);
+
+ writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+ tmc_enable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
+{
+ enum tmc_mem_intf_width memwidth;
+ u8 memwords;
+ char *bufp;
+ u32 read_data;
+ int i;
+
+ memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
+ if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
+ memwords = 1;
+ else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
+ memwords = 2;
+ else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
+ memwords = 4;
+ else
+ memwords = 8;
+
+ bufp = drvdata->buf;
+ while (1) {
+ for (i = 0; i < memwords; i++) {
+ read_data = readl_relaxed(drvdata->base + TMC_RRD);
+ if (read_data == 0xFFFFFFFF)
+ return;
+ memcpy(bufp, &read_data, 4);
+ bufp += 4;
+ }
+ }
+}
+
+void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
+{
+ CS_UNLOCK(drvdata->base);
+
+ tmc_flush_and_stop(drvdata);
+ tmc_etb_dump_hw(drvdata);
+ tmc_disable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
+{
+ CS_UNLOCK(drvdata->base);
+
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
+ writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
+ writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
+ drvdata->base + TMC_FFCR);
+ writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
+ tmc_enable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
+{
+ CS_UNLOCK(drvdata->base);
+
+ tmc_flush_and_stop(drvdata);
+ tmc_disable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
+{
+ unsigned long flags;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return -EBUSY;
+ }
+
+ tmc_etb_enable_hw(drvdata);
+ drvdata->enable = true;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n");
+ return 0;
+}
+
+static void tmc_disable_etf_sink(struct coresight_device *csdev)
+{
+ unsigned long flags;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return;
+ }
+
+ tmc_etb_disable_hw(drvdata);
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETB/ETF disabled\n");
+}
+
+static int tmc_enable_etf_link(struct coresight_device *csdev,
+ int inport, int outport)
+{
+ unsigned long flags;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return -EBUSY;
+ }
+
+ tmc_etf_enable_hw(drvdata);
+ drvdata->enable = true;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETF enabled\n");
+ return 0;
+}
+
+static void tmc_disable_etf_link(struct coresight_device *csdev,
+ int inport, int outport)
+{
+ unsigned long flags;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return;
+ }
+
+ tmc_etf_disable_hw(drvdata);
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC disabled\n");
+}
+
+static const struct coresight_ops_sink tmc_etf_sink_ops = {
+ .enable = tmc_enable_etf_sink,
+ .disable = tmc_disable_etf_sink,
+};
+
+static const struct coresight_ops_link tmc_etf_link_ops = {
+ .enable = tmc_enable_etf_link,
+ .disable = tmc_disable_etf_link,
+};
+
+const struct coresight_ops tmc_etb_cs_ops = {
+ .sink_ops = &tmc_etf_sink_ops,
+};
+
+const struct coresight_ops tmc_etf_cs_ops = {
+ .sink_ops = &tmc_etf_sink_ops,
+ .link_ops = &tmc_etf_link_ops,
+};
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
new file mode 100644
index 000000000000..5d9333ec49ae
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright(C) 2016 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/coresight.h>
+#include "coresight-priv.h"
+#include "coresight-tmc.h"
+
+void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
+{
+ u32 axictl;
+
+ /* Zero out the memory to help with debug */
+ memset(drvdata->vaddr, 0, drvdata->size);
+
+ CS_UNLOCK(drvdata->base);
+
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
+ writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
+ writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+
+ axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
+ axictl |= TMC_AXICTL_WR_BURST_16;
+ writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+ axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
+ writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+ axictl = (axictl &
+ ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
+ TMC_AXICTL_PROT_CTL_B1;
+ writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+
+ writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
+ writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
+ writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+ TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+ TMC_FFCR_TRIGON_TRIGIN,
+ drvdata->base + TMC_FFCR);
+ writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+ tmc_enable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
+{
+ u32 rwp, val;
+
+ rwp = readl_relaxed(drvdata->base + TMC_RWP);
+ val = readl_relaxed(drvdata->base + TMC_STS);
+
+ /* How much memory do we still have */
+ if (val & BIT(0))
+ drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
+ else
+ drvdata->buf = drvdata->vaddr;
+}
+
+void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
+{
+ CS_UNLOCK(drvdata->base);
+
+ tmc_flush_and_stop(drvdata);
+ tmc_etr_dump_hw(drvdata);
+ tmc_disable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
+{
+ unsigned long flags;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return -EBUSY;
+ }
+
+ tmc_etr_enable_hw(drvdata);
+ drvdata->enable = true;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETR enabled\n");
+ return 0;
+}
+
+static void tmc_disable_etr_sink(struct coresight_device *csdev)
+{
+ unsigned long flags;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return;
+ }
+
+ tmc_etr_disable_hw(drvdata);
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETR disabled\n");
+}
+
+static const struct coresight_ops_sink tmc_etr_sink_ops = {
+ .enable = tmc_enable_etr_sink,
+ .disable = tmc_disable_etr_sink,
+};
+
+const struct coresight_ops tmc_etr_cs_ops = {
+ .sink_ops = &tmc_etr_sink_ops,
+};
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 07e2809d832b..8d7f6d54c9b0 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -32,7 +32,7 @@
#include "coresight-priv.h"
#include "coresight-tmc.h"
-static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
+void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
{
/* Ensure formatter, unformatter and hardware fifo are empty */
if (coresight_timeout(drvdata->base,
@@ -43,7 +43,7 @@ static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
}
}
-static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
+void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
{
u32 ffcr;
@@ -63,272 +63,16 @@ static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
tmc_wait_for_tmcready(drvdata);
}
-static void tmc_enable_hw(struct tmc_drvdata *drvdata)
+void tmc_enable_hw(struct tmc_drvdata *drvdata)
{
writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
}
-static void tmc_disable_hw(struct tmc_drvdata *drvdata)
+void tmc_disable_hw(struct tmc_drvdata *drvdata)
{
writel_relaxed(0x0, drvdata->base + TMC_CTL);
}
-static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
-{
- /* Zero out the memory to help with debug */
- memset(drvdata->buf, 0, drvdata->size);
-
- CS_UNLOCK(drvdata->base);
-
- /* Wait for TMCSReady bit to be set */
- tmc_wait_for_tmcready(drvdata);
-
- writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
- writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
- TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
- TMC_FFCR_TRIGON_TRIGIN,
- drvdata->base + TMC_FFCR);
-
- writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
- tmc_enable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
-{
- u32 axictl;
-
- /* Zero out the memory to help with debug */
- memset(drvdata->vaddr, 0, drvdata->size);
-
- CS_UNLOCK(drvdata->base);
-
- /* Wait for TMCSReady bit to be set */
- tmc_wait_for_tmcready(drvdata);
-
- writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
- writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-
- axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
- axictl |= TMC_AXICTL_WR_BURST_16;
- writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
- axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
- writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
- axictl = (axictl &
- ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
- TMC_AXICTL_PROT_CTL_B1;
- writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-
- writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
- writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
- writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
- TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
- TMC_FFCR_TRIGON_TRIGIN,
- drvdata->base + TMC_FFCR);
- writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
- tmc_enable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
-{
- CS_UNLOCK(drvdata->base);
-
- /* Wait for TMCSReady bit to be set */
- tmc_wait_for_tmcready(drvdata);
-
- writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
- writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
- drvdata->base + TMC_FFCR);
- writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
- tmc_enable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->reading) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return -EBUSY;
- }
-
- if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
- tmc_etb_enable_hw(drvdata);
- } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- tmc_etr_enable_hw(drvdata);
- } else {
- if (mode == TMC_MODE_CIRCULAR_BUFFER)
- tmc_etb_enable_hw(drvdata);
- else
- tmc_etf_enable_hw(drvdata);
- }
- drvdata->enable = true;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
- dev_info(drvdata->dev, "TMC enabled\n");
- return 0;
-}
-
-static int tmc_enable_sink(struct coresight_device *csdev, u32 mode)
-{
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static int tmc_enable_link(struct coresight_device *csdev, int inport,
- int outport)
-{
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
-{
- enum tmc_mem_intf_width memwidth;
- u8 memwords;
- char *bufp;
- u32 read_data;
- int i;
-
- memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
- if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
- memwords = 1;
- else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
- memwords = 2;
- else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
- memwords = 4;
- else
- memwords = 8;
-
- bufp = drvdata->buf;
- while (1) {
- for (i = 0; i < memwords; i++) {
- read_data = readl_relaxed(drvdata->base + TMC_RRD);
- if (read_data == 0xFFFFFFFF)
- return;
- memcpy(bufp, &read_data, 4);
- bufp += 4;
- }
- }
-}
-
-static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
-{
- CS_UNLOCK(drvdata->base);
-
- tmc_flush_and_stop(drvdata);
- tmc_etb_dump_hw(drvdata);
- tmc_disable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
-{
- u32 rwp, val;
-
- rwp = readl_relaxed(drvdata->base + TMC_RWP);
- val = readl_relaxed(drvdata->base + TMC_STS);
-
- /* How much memory do we still have */
- if (val & BIT(0))
- drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
- else
- drvdata->buf = drvdata->vaddr;
-}
-
-static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
-{
- CS_UNLOCK(drvdata->base);
-
- tmc_flush_and_stop(drvdata);
- tmc_etr_dump_hw(drvdata);
- tmc_disable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
-{
- CS_UNLOCK(drvdata->base);
-
- tmc_flush_and_stop(drvdata);
- tmc_disable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->reading)
- goto out;
-
- if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
- tmc_etb_disable_hw(drvdata);
- } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- tmc_etr_disable_hw(drvdata);
- } else {
- if (mode == TMC_MODE_CIRCULAR_BUFFER)
- tmc_etb_disable_hw(drvdata);
- else
- tmc_etf_disable_hw(drvdata);
- }
-out:
- drvdata->enable = false;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
- dev_info(drvdata->dev, "TMC disabled\n");
-}
-
-static void tmc_disable_sink(struct coresight_device *csdev)
-{
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static void tmc_disable_link(struct coresight_device *csdev, int inport,
- int outport)
-{
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static const struct coresight_ops_sink tmc_sink_ops = {
- .enable = tmc_enable_sink,
- .disable = tmc_disable_sink,
-};
-
-static const struct coresight_ops_link tmc_link_ops = {
- .enable = tmc_enable_link,
- .disable = tmc_disable_link,
-};
-
-static const struct coresight_ops tmc_etb_cs_ops = {
- .sink_ops = &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etr_cs_ops = {
- .sink_ops = &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etf_cs_ops = {
- .sink_ops = &tmc_sink_ops,
- .link_ops = &tmc_link_ops,
-};
-
static int tmc_read_prepare(struct tmc_drvdata *drvdata)
{
int ret = 0;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 5a60830c8db5..b3017e115c4d 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -18,6 +18,8 @@
#ifndef _CORESIGHT_TMC_H
#define _CORESIGHT_TMC_H
+#include <linux/miscdevice.h>
+
#define TMC_RSZ 0x004
#define TMC_STS 0x00c
#define TMC_RRD 0x010
@@ -118,4 +120,20 @@ struct tmc_drvdata {
u32 trigger_cntr;
};
+/* Generic functions */
+void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata);
+void tmc_flush_and_stop(struct tmc_drvdata *drvdata);
+void tmc_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_disable_hw(struct tmc_drvdata *drvdata);
+
+/* ETB/ETF functions */
+void tmc_etb_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_etb_disable_hw(struct tmc_drvdata *drvdata);
+extern const struct coresight_ops tmc_etb_cs_ops;
+extern const struct coresight_ops tmc_etf_cs_ops;
+
+/* ETR functions */
+void tmc_etr_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_etr_disable_hw(struct tmc_drvdata *drvdata);
+extern const struct coresight_ops tmc_etr_cs_ops;
#endif
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 03/18] coresight: tmc: re-implementing tmc_read_prepare/unprepare() functions |
| Message-ID | <rqMUj-5Du-45@gated-at.bofh.it> |
| In reply to | #1385379 |
In their current implementation the tmc_read_prepare/unprepare()
are a lump of if/else that is difficult to read. This patch is
alleviating that by using a switch statement. The latter also
allows for a better control on the error path.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc.c | 56 ++++++++++++++++++-----------
1 file changed, 36 insertions(+), 20 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 66fa7736d12f..d211aeec49f8 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -431,7 +431,7 @@ static const struct coresight_ops tmc_etf_cs_ops = {
static int tmc_read_prepare(struct tmc_drvdata *drvdata)
{
- int ret;
+ int ret = 0;
unsigned long flags;
enum tmc_mode mode;
@@ -439,25 +439,31 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata)
if (!drvdata->enable)
goto out;
- if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+ switch (drvdata->config_type) {
+ case TMC_CONFIG_TYPE_ETB:
tmc_etb_disable_hw(drvdata);
- } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- tmc_etr_disable_hw(drvdata);
- } else {
+ break;
+ case TMC_CONFIG_TYPE_ETF:
+ /* There is no point in reading a TMC in HW FIFO mode */
mode = readl_relaxed(drvdata->base + TMC_MODE);
- if (mode == TMC_MODE_CIRCULAR_BUFFER) {
- tmc_etb_disable_hw(drvdata);
- } else {
- ret = -ENODEV;
+ if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+ ret = -EINVAL;
goto err;
}
+
+ tmc_etb_disable_hw(drvdata);
+ break;
+ case TMC_CONFIG_TYPE_ETR:
+ tmc_etr_disable_hw(drvdata);
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
}
+
out:
drvdata->reading = true;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
dev_info(drvdata->dev, "TMC read start\n");
- return 0;
err:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return ret;
@@ -472,20 +478,30 @@ static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
if (!drvdata->enable)
goto out;
- if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+ switch (drvdata->config_type) {
+ case TMC_CONFIG_TYPE_ETB:
tmc_etb_enable_hw(drvdata);
- } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- tmc_etr_enable_hw(drvdata);
- } else {
+ break;
+ case TMC_CONFIG_TYPE_ETF:
+ /* Make sure we don't re-enable a TMC in HW FIFO mode */
mode = readl_relaxed(drvdata->base + TMC_MODE);
- if (mode == TMC_MODE_CIRCULAR_BUFFER)
- tmc_etb_enable_hw(drvdata);
+ if (mode != TMC_MODE_CIRCULAR_BUFFER)
+ goto err;
+
+ tmc_etb_enable_hw(drvdata);
+ break;
+ case TMC_CONFIG_TYPE_ETR:
+ tmc_etr_disable_hw(drvdata);
+ break;
+ default:
+ goto err;
}
+
out:
drvdata->reading = false;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
dev_info(drvdata->dev, "TMC read end\n");
+err:
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
}
static int tmc_open(struct inode *inode, struct file *file)
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 15/18] coresight: moving struct cs_buffers to header file |
| Message-ID | <rqMUj-5Du-51@gated-at.bofh.it> |
| In reply to | #1385379 |
That way we can re-use the structure in other drivers.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight-etb10.c | 20 --------------------
drivers/hwtracing/coresight/coresight-priv.h | 20 ++++++++++++++++++++
2 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index a974c39171a9..239800aa5e24 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -71,26 +71,6 @@
#define ETB_FRAME_SIZE_WORDS 4
/**
- * struct cs_buffer - keep track of a recording session' specifics
- * @cur: index of the current buffer
- * @nr_pages: max number of pages granted to us
- * @offset: offset within the current buffer
- * @data_size: how much we collected in this run
- * @lost: other than zero if we had a HW buffer wrap around
- * @snapshot: is this run in snapshot mode
- * @data_pages: a handle the ring buffer
- */
-struct cs_buffers {
- unsigned int cur;
- unsigned int nr_pages;
- unsigned long offset;
- local_t data_size;
- local_t lost;
- bool snapshot;
- void **data_pages;
-};
-
-/**
* struct etb_drvdata - specifics associated to an ETB component
* @base: memory mapped base address for this component.
* @dev: the device entity associated to this component.
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 3b5dd95a3588..ad975c58080d 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -53,6 +53,26 @@ enum cs_mode {
CS_MODE_PERF,
};
+/**
+ * struct cs_buffer - keep track of a recording session' specifics
+ * @cur: index of the current buffer
+ * @nr_pages: max number of pages granted to us
+ * @offset: offset within the current buffer
+ * @data_size: how much we collected in this run
+ * @lost: other than zero if we had a HW buffer wrap around
+ * @snapshot: is this run in snapshot mode
+ * @data_pages: a handle the ring buffer
+ */
+struct cs_buffers {
+ unsigned int cur;
+ unsigned int nr_pages;
+ unsigned long offset;
+ local_t data_size;
+ local_t lost;
+ bool snapshot;
+ void **data_pages;
+};
+
static inline void CS_LOCK(void __iomem *addr)
{
do {
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-22 19:20 +0200 |
| Subject | [PATCH V3 05/18] coresight: tmc: introducing new header file |
| Message-ID | <rqMUk-5Du-53@gated-at.bofh.it> |
| In reply to | #1385379 |
The amount of #define, enumeration and structure definition
is big enough to justify moving them to a new header file.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc.c | 102 +----------------------
drivers/hwtracing/coresight/coresight-tmc.h | 122 ++++++++++++++++++++++++++++
2 files changed, 123 insertions(+), 101 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-tmc.h
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 8751d53fa078..f9a6624ab531 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -30,107 +30,7 @@
#include <linux/amba/bus.h>
#include "coresight-priv.h"
-
-#define TMC_RSZ 0x004
-#define TMC_STS 0x00c
-#define TMC_RRD 0x010
-#define TMC_RRP 0x014
-#define TMC_RWP 0x018
-#define TMC_TRG 0x01c
-#define TMC_CTL 0x020
-#define TMC_RWD 0x024
-#define TMC_MODE 0x028
-#define TMC_LBUFLEVEL 0x02c
-#define TMC_CBUFLEVEL 0x030
-#define TMC_BUFWM 0x034
-#define TMC_RRPHI 0x038
-#define TMC_RWPHI 0x03c
-#define TMC_AXICTL 0x110
-#define TMC_DBALO 0x118
-#define TMC_DBAHI 0x11c
-#define TMC_FFSR 0x300
-#define TMC_FFCR 0x304
-#define TMC_PSCR 0x308
-#define TMC_ITMISCOP0 0xee0
-#define TMC_ITTRFLIN 0xee8
-#define TMC_ITATBDATA0 0xeec
-#define TMC_ITATBCTR2 0xef0
-#define TMC_ITATBCTR1 0xef4
-#define TMC_ITATBCTR0 0xef8
-
-/* register description */
-/* TMC_CTL - 0x020 */
-#define TMC_CTL_CAPT_EN BIT(0)
-/* TMC_STS - 0x00C */
-#define TMC_STS_TRIGGERED BIT(1)
-/* TMC_AXICTL - 0x110 */
-#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
-#define TMC_AXICTL_PROT_CTL_B1 BIT(1)
-#define TMC_AXICTL_SCT_GAT_MODE BIT(7)
-#define TMC_AXICTL_WR_BURST_16 0xF00
-/* TMC_FFCR - 0x304 */
-#define TMC_FFCR_EN_FMT BIT(0)
-#define TMC_FFCR_EN_TI BIT(1)
-#define TMC_FFCR_FON_FLIN BIT(4)
-#define TMC_FFCR_FON_TRIG_EVT BIT(5)
-#define TMC_FFCR_FLUSHMAN BIT(6)
-#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
-#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
-
-#define TMC_STS_TMCREADY_BIT 2
-#define TMC_FFCR_FLUSHMAN_BIT 6
-
-enum tmc_config_type {
- TMC_CONFIG_TYPE_ETB,
- TMC_CONFIG_TYPE_ETR,
- TMC_CONFIG_TYPE_ETF,
-};
-
-enum tmc_mode {
- TMC_MODE_CIRCULAR_BUFFER,
- TMC_MODE_SOFTWARE_FIFO,
- TMC_MODE_HARDWARE_FIFO,
-};
-
-enum tmc_mem_intf_width {
- TMC_MEM_INTF_WIDTH_32BITS = 0x2,
- TMC_MEM_INTF_WIDTH_64BITS = 0x3,
- TMC_MEM_INTF_WIDTH_128BITS = 0x4,
- TMC_MEM_INTF_WIDTH_256BITS = 0x5,
-};
-
-/**
- * struct tmc_drvdata - specifics associated to an TMC component
- * @base: memory mapped base address for this component.
- * @dev: the device entity associated to this component.
- * @csdev: component vitals needed by the framework.
- * @miscdev: specifics to handle "/dev/xyz.tmc" entry.
- * @spinlock: only one at a time pls.
- * @read_count: manages preparation of buffer for reading.
- * @buf: area of memory where trace data get sent.
- * @paddr: DMA start location in RAM.
- * @vaddr: virtual representation of @paddr.
- * @size: @buf size.
- * @enable: this TMC is being used.
- * @config_type: TMC variant, must be of type @tmc_config_type.
- * @trigger_cntr: amount of words to store after a trigger.
- */
-struct tmc_drvdata {
- void __iomem *base;
- struct device *dev;
- struct coresight_device *csdev;
- struct miscdevice miscdev;
- spinlock_t spinlock;
- int read_count;
- bool reading;
- char *buf;
- dma_addr_t paddr;
- void *vaddr;
- u32 size;
- bool enable;
- enum tmc_config_type config_type;
- u32 trigger_cntr;
-};
+#include "coresight-tmc.h"
static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
{
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
new file mode 100644
index 000000000000..49718b4a9788
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CORESIGHT_TMC_H
+#define _CORESIGHT_TMC_H
+
+#define TMC_RSZ 0x004
+#define TMC_STS 0x00c
+#define TMC_RRD 0x010
+#define TMC_RRP 0x014
+#define TMC_RWP 0x018
+#define TMC_TRG 0x01c
+#define TMC_CTL 0x020
+#define TMC_RWD 0x024
+#define TMC_MODE 0x028
+#define TMC_LBUFLEVEL 0x02c
+#define TMC_CBUFLEVEL 0x030
+#define TMC_BUFWM 0x034
+#define TMC_RRPHI 0x038
+#define TMC_RWPHI 0x03c
+#define TMC_AXICTL 0x110
+#define TMC_DBALO 0x118
+#define TMC_DBAHI 0x11c
+#define TMC_FFSR 0x300
+#define TMC_FFCR 0x304
+#define TMC_PSCR 0x308
+#define TMC_ITMISCOP0 0xee0
+#define TMC_ITTRFLIN 0xee8
+#define TMC_ITATBDATA0 0xeec
+#define TMC_ITATBCTR2 0xef0
+#define TMC_ITATBCTR1 0xef4
+#define TMC_ITATBCTR0 0xef8
+
+/* register description */
+/* TMC_CTL - 0x020 */
+#define TMC_CTL_CAPT_EN BIT(0)
+/* TMC_STS - 0x00C */
+#define TMC_STS_TRIGGERED BIT(1)
+/* TMC_AXICTL - 0x110 */
+#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
+#define TMC_AXICTL_PROT_CTL_B1 BIT(1)
+#define TMC_AXICTL_SCT_GAT_MODE BIT(7)
+#define TMC_AXICTL_WR_BURST_16 0xF00
+/* TMC_FFCR - 0x304 */
+#define TMC_FFCR_EN_FMT BIT(0)
+#define TMC_FFCR_EN_TI BIT(1)
+#define TMC_FFCR_FON_FLIN BIT(4)
+#define TMC_FFCR_FON_TRIG_EVT BIT(5)
+#define TMC_FFCR_FLUSHMAN BIT(6)
+#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
+#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
+
+#define TMC_STS_TMCREADY_BIT 2
+#define TMC_FFCR_FLUSHMAN_BIT 6
+
+enum tmc_config_type {
+ TMC_CONFIG_TYPE_ETB,
+ TMC_CONFIG_TYPE_ETR,
+ TMC_CONFIG_TYPE_ETF,
+};
+
+enum tmc_mode {
+ TMC_MODE_CIRCULAR_BUFFER,
+ TMC_MODE_SOFTWARE_FIFO,
+ TMC_MODE_HARDWARE_FIFO,
+};
+
+enum tmc_mem_intf_width {
+ TMC_MEM_INTF_WIDTH_32BITS = 0x2,
+ TMC_MEM_INTF_WIDTH_64BITS = 0x3,
+ TMC_MEM_INTF_WIDTH_128BITS = 0x4,
+ TMC_MEM_INTF_WIDTH_256BITS = 0x5,
+};
+
+/**
+ * struct tmc_drvdata - specifics associated to an TMC component
+ * @base: memory mapped base address for this component.
+ * @dev: the device entity associated to this component.
+ * @csdev: component vitals needed by the framework.
+ * @miscdev: specifics to handle "/dev/xyz.tmc" entry.
+ * @spinlock: only one at a time pls.
+ * @read_count: manages preparation of buffer for reading.
+ * @buf: area of memory where trace data get sent.
+ * @paddr: DMA start location in RAM.
+ * @vaddr: virtual representation of @paddr.
+ * @size: @buf size.
+ * @enable: this TMC is being used.
+ * @config_type: TMC variant, must be of type @tmc_config_type.
+ * @trigger_cntr: amount of words to store after a trigger.
+ */
+struct tmc_drvdata {
+ void __iomem *base;
+ struct device *dev;
+ struct coresight_device *csdev;
+ struct miscdevice miscdev;
+ spinlock_t spinlock;
+ int read_count;
+ bool reading;
+ char *buf;
+ dma_addr_t paddr;
+ void __iomem *vaddr;
+ u32 size;
+ bool enable;
+ enum tmc_config_type config_type;
+ u32 trigger_cntr;
+};
+
+#endif
--
2.5.0
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web