Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
[linux-block.git] / drivers / hwtracing / coresight / coresight-tmc-etr.c
CommitLineData
6c6ed1e2
MP
1/*
2 * Copyright(C) 2016 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
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.
8 *
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
12 * more details.
13 *
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/>.
16 */
17
18#include <linux/coresight.h>
de546197 19#include <linux/dma-mapping.h>
6c6ed1e2
MP
20#include "coresight-priv.h"
21#include "coresight-tmc.h"
22
0ef7528d 23static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
6c6ed1e2 24{
f2e931a2 25 u32 axictl, sts;
6c6ed1e2
MP
26
27 /* Zero out the memory to help with debug */
28 memset(drvdata->vaddr, 0, drvdata->size);
29
30 CS_UNLOCK(drvdata->base);
31
32 /* Wait for TMCSReady bit to be set */
33 tmc_wait_for_tmcready(drvdata);
34
35 writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
36 writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
37
38 axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
cd407abd
SP
39 axictl &= ~TMC_AXICTL_CLEAR_MASK;
40 axictl |= (TMC_AXICTL_PROT_CTL_B1 | TMC_AXICTL_WR_BURST_16);
41 axictl |= TMC_AXICTL_AXCACHE_OS;
ebab6a7d
SP
42
43 if (tmc_etr_has_cap(drvdata, TMC_ETR_AXI_ARCACHE)) {
44 axictl &= ~TMC_AXICTL_ARCACHE_MASK;
45 axictl |= TMC_AXICTL_ARCACHE_OS;
46 }
47
6c6ed1e2 48 writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
6f6ab4fc 49 tmc_write_dba(drvdata, drvdata->paddr);
f2e931a2
SP
50 /*
51 * If the TMC pointers must be programmed before the session,
52 * we have to set it properly (i.e, RRP/RWP to base address and
53 * STS to "not full").
54 */
55 if (tmc_etr_has_cap(drvdata, TMC_ETR_SAVE_RESTORE)) {
56 tmc_write_rrp(drvdata, drvdata->paddr);
57 tmc_write_rwp(drvdata, drvdata->paddr);
58 sts = readl_relaxed(drvdata->base + TMC_STS) & ~TMC_STS_FULL;
59 writel_relaxed(sts, drvdata->base + TMC_STS);
60 }
6c6ed1e2 61
6c6ed1e2
MP
62 writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
63 TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
64 TMC_FFCR_TRIGON_TRIGIN,
65 drvdata->base + TMC_FFCR);
66 writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
67 tmc_enable_hw(drvdata);
68
69 CS_LOCK(drvdata->base);
70}
71
72static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
73{
0c3fc4d5 74 const u32 *barrier;
6f6ab4fc 75 u32 val;
0c3fc4d5 76 u32 *temp;
6f6ab4fc 77 u64 rwp;
6c6ed1e2 78
6f6ab4fc 79 rwp = tmc_read_rwp(drvdata);
6c6ed1e2
MP
80 val = readl_relaxed(drvdata->base + TMC_STS);
81
8505feae
SP
82 /*
83 * Adjust the buffer to point to the beginning of the trace data
84 * and update the available trace data.
85 */
1c9cbe11 86 if (val & TMC_STS_FULL) {
6c6ed1e2 87 drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
8505feae 88 drvdata->len = drvdata->size;
0c3fc4d5
MP
89
90 barrier = barrier_pkt;
91 temp = (u32 *)drvdata->buf;
92
93 while (*barrier) {
94 *temp = *barrier;
95 temp++;
96 barrier++;
97 }
98
8505feae 99 } else {
6c6ed1e2 100 drvdata->buf = drvdata->vaddr;
8505feae
SP
101 drvdata->len = rwp - drvdata->paddr;
102 }
6c6ed1e2
MP
103}
104
4525412a 105static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
6c6ed1e2
MP
106{
107 CS_UNLOCK(drvdata->base);
108
109 tmc_flush_and_stop(drvdata);
a40318fb
MP
110 /*
111 * When operating in sysFS mode the content of the buffer needs to be
112 * read before the TMC is disabled.
113 */
297ab90f 114 if (drvdata->mode == CS_MODE_SYSFS)
a40318fb 115 tmc_etr_dump_hw(drvdata);
6c6ed1e2
MP
116 tmc_disable_hw(drvdata);
117
118 CS_LOCK(drvdata->base);
119}
120
c38e505e 121static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
6c6ed1e2 122{
de546197
MP
123 int ret = 0;
124 bool used = false;
6c6ed1e2 125 unsigned long flags;
de546197
MP
126 void __iomem *vaddr = NULL;
127 dma_addr_t paddr;
6c6ed1e2
MP
128 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
129
de546197
MP
130
131 /*
132 * If we don't have a buffer release the lock and allocate memory.
133 * Otherwise keep the lock and move along.
134 */
6c6ed1e2 135 spin_lock_irqsave(&drvdata->spinlock, flags);
de546197 136 if (!drvdata->vaddr) {
6c6ed1e2 137 spin_unlock_irqrestore(&drvdata->spinlock, flags);
de546197
MP
138
139 /*
140 * Contiguous memory can't be allocated while a spinlock is
141 * held. As such allocate memory here and free it if a buffer
142 * has already been allocated (from a previous session).
143 */
144 vaddr = dma_alloc_coherent(drvdata->dev, drvdata->size,
145 &paddr, GFP_KERNEL);
146 if (!vaddr)
147 return -ENOMEM;
148
149 /* Let's try again */
150 spin_lock_irqsave(&drvdata->spinlock, flags);
151 }
152
153 if (drvdata->reading) {
154 ret = -EBUSY;
155 goto out;
156 }
157
f2facc33
MP
158 /*
159 * In sysFS mode we can have multiple writers per sink. Since this
160 * sink is already enabled no memory is needed and the HW need not be
161 * touched.
162 */
297ab90f 163 if (drvdata->mode == CS_MODE_SYSFS)
f2facc33
MP
164 goto out;
165
de546197
MP
166 /*
167 * If drvdata::buf == NULL, use the memory allocated above.
168 * Otherwise a buffer still exists from a previous session, so
169 * simply use that.
170 */
171 if (drvdata->buf == NULL) {
172 used = true;
173 drvdata->vaddr = vaddr;
174 drvdata->paddr = paddr;
175 drvdata->buf = drvdata->vaddr;
6c6ed1e2
MP
176 }
177
297ab90f 178 drvdata->mode = CS_MODE_SYSFS;
6c6ed1e2 179 tmc_etr_enable_hw(drvdata);
de546197 180out:
6c6ed1e2
MP
181 spin_unlock_irqrestore(&drvdata->spinlock, flags);
182
de546197
MP
183 /* Free memory outside the spinlock if need be */
184 if (!used && vaddr)
185 dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
186
187 if (!ret)
188 dev_info(drvdata->dev, "TMC-ETR enabled\n");
189
190 return ret;
6c6ed1e2
MP
191}
192
c38e505e 193static int tmc_enable_etr_sink_perf(struct coresight_device *csdev)
b217601e
MP
194{
195 int ret = 0;
b217601e
MP
196 unsigned long flags;
197 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
198
b217601e
MP
199 spin_lock_irqsave(&drvdata->spinlock, flags);
200 if (drvdata->reading) {
201 ret = -EINVAL;
202 goto out;
203 }
204
b217601e
MP
205 /*
206 * In Perf mode there can be only one writer per sink. There
207 * is also no need to continue if the ETR is already operated
208 * from sysFS.
209 */
297ab90f 210 if (drvdata->mode != CS_MODE_DISABLED) {
b217601e
MP
211 ret = -EINVAL;
212 goto out;
213 }
214
297ab90f 215 drvdata->mode = CS_MODE_PERF;
b217601e
MP
216 tmc_etr_enable_hw(drvdata);
217out:
218 spin_unlock_irqrestore(&drvdata->spinlock, flags);
219
220 return ret;
221}
222
223static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
224{
225 switch (mode) {
226 case CS_MODE_SYSFS:
c38e505e 227 return tmc_enable_etr_sink_sysfs(csdev);
b217601e 228 case CS_MODE_PERF:
c38e505e 229 return tmc_enable_etr_sink_perf(csdev);
b217601e
MP
230 }
231
232 /* We shouldn't be here */
233 return -EINVAL;
234}
235
6c6ed1e2
MP
236static void tmc_disable_etr_sink(struct coresight_device *csdev)
237{
238 unsigned long flags;
239 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
240
241 spin_lock_irqsave(&drvdata->spinlock, flags);
242 if (drvdata->reading) {
243 spin_unlock_irqrestore(&drvdata->spinlock, flags);
244 return;
245 }
246
f2facc33 247 /* Disable the TMC only if it needs to */
297ab90f 248 if (drvdata->mode != CS_MODE_DISABLED) {
f2facc33 249 tmc_etr_disable_hw(drvdata);
297ab90f
SP
250 drvdata->mode = CS_MODE_DISABLED;
251 }
f2facc33 252
6c6ed1e2
MP
253 spin_unlock_irqrestore(&drvdata->spinlock, flags);
254
255 dev_info(drvdata->dev, "TMC-ETR disabled\n");
256}
257
258static const struct coresight_ops_sink tmc_etr_sink_ops = {
259 .enable = tmc_enable_etr_sink,
260 .disable = tmc_disable_etr_sink,
261};
262
263const struct coresight_ops tmc_etr_cs_ops = {
264 .sink_ops = &tmc_etr_sink_ops,
265};
4525412a
MP
266
267int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
268{
de546197 269 int ret = 0;
4525412a
MP
270 unsigned long flags;
271
272 /* config types are set a boot time and never change */
273 if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
274 return -EINVAL;
275
276 spin_lock_irqsave(&drvdata->spinlock, flags);
f74debbe
MP
277 if (drvdata->reading) {
278 ret = -EBUSY;
279 goto out;
280 }
4525412a 281
b217601e 282 /* Don't interfere if operated from Perf */
297ab90f 283 if (drvdata->mode == CS_MODE_PERF) {
b217601e
MP
284 ret = -EINVAL;
285 goto out;
286 }
287
de546197
MP
288 /* If drvdata::buf is NULL the trace data has been read already */
289 if (drvdata->buf == NULL) {
290 ret = -EINVAL;
291 goto out;
292 }
293
4525412a 294 /* Disable the TMC if need be */
297ab90f 295 if (drvdata->mode == CS_MODE_SYSFS)
4525412a
MP
296 tmc_etr_disable_hw(drvdata);
297
298 drvdata->reading = true;
de546197 299out:
4525412a
MP
300 spin_unlock_irqrestore(&drvdata->spinlock, flags);
301
b217601e 302 return ret;
4525412a
MP
303}
304
305int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
306{
307 unsigned long flags;
de546197
MP
308 dma_addr_t paddr;
309 void __iomem *vaddr = NULL;
4525412a
MP
310
311 /* config types are set a boot time and never change */
312 if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
313 return -EINVAL;
314
315 spin_lock_irqsave(&drvdata->spinlock, flags);
316
317 /* RE-enable the TMC if need be */
297ab90f 318 if (drvdata->mode == CS_MODE_SYSFS) {
de546197
MP
319 /*
320 * The trace run will continue with the same allocated trace
f3b8172f
SP
321 * buffer. The trace buffer is cleared in tmc_etr_enable_hw(),
322 * so we don't have to explicitly clear it. Also, since the
323 * tracer is still enabled drvdata::buf can't be NULL.
de546197 324 */
4525412a 325 tmc_etr_enable_hw(drvdata);
de546197
MP
326 } else {
327 /*
328 * The ETR is not tracing and the buffer was just read.
329 * As such prepare to free the trace buffer.
330 */
331 vaddr = drvdata->vaddr;
332 paddr = drvdata->paddr;
8e215298 333 drvdata->buf = drvdata->vaddr = NULL;
de546197 334 }
4525412a
MP
335
336 drvdata->reading = false;
337 spin_unlock_irqrestore(&drvdata->spinlock, flags);
338
de546197
MP
339 /* Free allocated memory out side of the spinlock */
340 if (vaddr)
341 dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
342
4525412a
MP
343 return 0;
344}