2 * Copyright(C) 2016 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
18 #include <linux/coresight.h>
19 #include <linux/dma-mapping.h>
20 #include "coresight-priv.h"
21 #include "coresight-tmc.h"
23 void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
27 /* Zero out the memory to help with debug */
28 memset(drvdata->vaddr, 0, drvdata->size);
30 CS_UNLOCK(drvdata->base);
32 /* Wait for TMCSReady bit to be set */
33 tmc_wait_for_tmcready(drvdata);
35 writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
36 writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
38 axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
39 axictl |= TMC_AXICTL_WR_BURST_16;
40 writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
41 axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
42 writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
44 ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
45 TMC_AXICTL_PROT_CTL_B1;
46 writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
48 writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
49 writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
50 writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
51 TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
52 TMC_FFCR_TRIGON_TRIGIN,
53 drvdata->base + TMC_FFCR);
54 writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
55 tmc_enable_hw(drvdata);
57 CS_LOCK(drvdata->base);
60 static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
64 rwp = readl_relaxed(drvdata->base + TMC_RWP);
65 val = readl_relaxed(drvdata->base + TMC_STS);
67 /* How much memory do we still have */
69 drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
71 drvdata->buf = drvdata->vaddr;
74 static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
76 CS_UNLOCK(drvdata->base);
78 tmc_flush_and_stop(drvdata);
79 tmc_etr_dump_hw(drvdata);
80 tmc_disable_hw(drvdata);
82 CS_LOCK(drvdata->base);
85 static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
90 void __iomem *vaddr = NULL;
92 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
94 /* This shouldn't be happening */
95 if (WARN_ON(mode != CS_MODE_SYSFS))
99 * If we don't have a buffer release the lock and allocate memory.
100 * Otherwise keep the lock and move along.
102 spin_lock_irqsave(&drvdata->spinlock, flags);
103 if (!drvdata->vaddr) {
104 spin_unlock_irqrestore(&drvdata->spinlock, flags);
107 * Contiguous memory can't be allocated while a spinlock is
108 * held. As such allocate memory here and free it if a buffer
109 * has already been allocated (from a previous session).
111 vaddr = dma_alloc_coherent(drvdata->dev, drvdata->size,
116 /* Let's try again */
117 spin_lock_irqsave(&drvdata->spinlock, flags);
120 if (drvdata->reading) {
126 * If drvdata::buf == NULL, use the memory allocated above.
127 * Otherwise a buffer still exists from a previous session, so
130 if (drvdata->buf == NULL) {
132 drvdata->vaddr = vaddr;
133 drvdata->paddr = paddr;
134 drvdata->buf = drvdata->vaddr;
137 memset(drvdata->vaddr, 0, drvdata->size);
139 tmc_etr_enable_hw(drvdata);
140 drvdata->enable = true;
142 spin_unlock_irqrestore(&drvdata->spinlock, flags);
144 /* Free memory outside the spinlock if need be */
146 dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
149 dev_info(drvdata->dev, "TMC-ETR enabled\n");
154 static void tmc_disable_etr_sink(struct coresight_device *csdev)
157 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
159 spin_lock_irqsave(&drvdata->spinlock, flags);
160 if (drvdata->reading) {
161 spin_unlock_irqrestore(&drvdata->spinlock, flags);
165 tmc_etr_disable_hw(drvdata);
166 drvdata->enable = false;
167 spin_unlock_irqrestore(&drvdata->spinlock, flags);
169 dev_info(drvdata->dev, "TMC-ETR disabled\n");
172 static const struct coresight_ops_sink tmc_etr_sink_ops = {
173 .enable = tmc_enable_etr_sink,
174 .disable = tmc_disable_etr_sink,
177 const struct coresight_ops tmc_etr_cs_ops = {
178 .sink_ops = &tmc_etr_sink_ops,
181 int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
186 /* config types are set a boot time and never change */
187 if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
190 spin_lock_irqsave(&drvdata->spinlock, flags);
191 if (drvdata->reading) {
196 /* If drvdata::buf is NULL the trace data has been read already */
197 if (drvdata->buf == NULL) {
202 /* Disable the TMC if need be */
204 tmc_etr_disable_hw(drvdata);
206 drvdata->reading = true;
208 spin_unlock_irqrestore(&drvdata->spinlock, flags);
213 int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
217 void __iomem *vaddr = NULL;
219 /* config types are set a boot time and never change */
220 if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
223 spin_lock_irqsave(&drvdata->spinlock, flags);
225 /* RE-enable the TMC if need be */
226 if (drvdata->enable) {
228 * The trace run will continue with the same allocated trace
229 * buffer. As such zero-out the buffer so that we don't end
230 * up with stale data.
232 * Since the tracer is still enabled drvdata::buf
235 memset(drvdata->buf, 0, drvdata->size);
236 tmc_etr_enable_hw(drvdata);
239 * The ETR is not tracing and the buffer was just read.
240 * As such prepare to free the trace buffer.
242 vaddr = drvdata->vaddr;
243 paddr = drvdata->paddr;
247 drvdata->reading = false;
248 spin_unlock_irqrestore(&drvdata->spinlock, flags);
250 /* Free allocated memory out side of the spinlock */
252 dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);