GNU Linux-libre 4.9.337-gnu1
[releases.git] / drivers / hwtracing / coresight / coresight-tmc-etr.c
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>
19 #include <linux/dma-mapping.h>
20 #include "coresight-priv.h"
21 #include "coresight-tmc.h"
22
23 static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
24 {
25         u32 axictl;
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);
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);
43         axictl = (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);
47
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);
56
57         CS_LOCK(drvdata->base);
58 }
59
60 static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
61 {
62         u32 rwp, val;
63
64         rwp = readl_relaxed(drvdata->base + TMC_RWP);
65         val = readl_relaxed(drvdata->base + TMC_STS);
66
67         /*
68          * Adjust the buffer to point to the beginning of the trace data
69          * and update the available trace data.
70          */
71         if (val & TMC_STS_FULL) {
72                 drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
73                 drvdata->len = drvdata->size;
74         } else {
75                 drvdata->buf = drvdata->vaddr;
76                 drvdata->len = rwp - drvdata->paddr;
77         }
78 }
79
80 static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
81 {
82         CS_UNLOCK(drvdata->base);
83
84         tmc_flush_and_stop(drvdata);
85         /*
86          * When operating in sysFS mode the content of the buffer needs to be
87          * read before the TMC is disabled.
88          */
89         if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
90                 tmc_etr_dump_hw(drvdata);
91         tmc_disable_hw(drvdata);
92
93         CS_LOCK(drvdata->base);
94 }
95
96 static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
97 {
98         int ret = 0;
99         bool used = false;
100         long val;
101         unsigned long flags;
102         void __iomem *vaddr = NULL;
103         dma_addr_t paddr;
104         struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
105
106          /* This shouldn't be happening */
107         if (WARN_ON(mode != CS_MODE_SYSFS))
108                 return -EINVAL;
109
110         /*
111          * If we don't have a buffer release the lock and allocate memory.
112          * Otherwise keep the lock and move along.
113          */
114         spin_lock_irqsave(&drvdata->spinlock, flags);
115         if (!drvdata->vaddr) {
116                 spin_unlock_irqrestore(&drvdata->spinlock, flags);
117
118                 /*
119                  * Contiguous  memory can't be allocated while a spinlock is
120                  * held.  As such allocate memory here and free it if a buffer
121                  * has already been allocated (from a previous session).
122                  */
123                 vaddr = dma_alloc_coherent(drvdata->dev, drvdata->size,
124                                            &paddr, GFP_KERNEL);
125                 if (!vaddr)
126                         return -ENOMEM;
127
128                 /* Let's try again */
129                 spin_lock_irqsave(&drvdata->spinlock, flags);
130         }
131
132         if (drvdata->reading) {
133                 ret = -EBUSY;
134                 goto out;
135         }
136
137         val = local_xchg(&drvdata->mode, mode);
138         /*
139          * In sysFS mode we can have multiple writers per sink.  Since this
140          * sink is already enabled no memory is needed and the HW need not be
141          * touched.
142          */
143         if (val == CS_MODE_SYSFS)
144                 goto out;
145
146         /*
147          * If drvdata::buf == NULL, use the memory allocated above.
148          * Otherwise a buffer still exists from a previous session, so
149          * simply use that.
150          */
151         if (drvdata->buf == NULL) {
152                 used = true;
153                 drvdata->vaddr = vaddr;
154                 drvdata->paddr = paddr;
155                 drvdata->buf = drvdata->vaddr;
156         }
157
158         memset(drvdata->vaddr, 0, drvdata->size);
159
160         tmc_etr_enable_hw(drvdata);
161 out:
162         spin_unlock_irqrestore(&drvdata->spinlock, flags);
163
164         /* Free memory outside the spinlock if need be */
165         if (!used && vaddr)
166                 dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
167
168         if (!ret)
169                 dev_info(drvdata->dev, "TMC-ETR enabled\n");
170
171         return ret;
172 }
173
174 static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
175 {
176         int ret = 0;
177         long val;
178         unsigned long flags;
179         struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
180
181          /* This shouldn't be happening */
182         if (WARN_ON(mode != CS_MODE_PERF))
183                 return -EINVAL;
184
185         spin_lock_irqsave(&drvdata->spinlock, flags);
186         if (drvdata->reading) {
187                 ret = -EINVAL;
188                 goto out;
189         }
190
191         val = local_xchg(&drvdata->mode, mode);
192         /*
193          * In Perf mode there can be only one writer per sink.  There
194          * is also no need to continue if the ETR is already operated
195          * from sysFS.
196          */
197         if (val != CS_MODE_DISABLED) {
198                 ret = -EINVAL;
199                 goto out;
200         }
201
202         tmc_etr_enable_hw(drvdata);
203 out:
204         spin_unlock_irqrestore(&drvdata->spinlock, flags);
205
206         return ret;
207 }
208
209 static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
210 {
211         switch (mode) {
212         case CS_MODE_SYSFS:
213                 return tmc_enable_etr_sink_sysfs(csdev, mode);
214         case CS_MODE_PERF:
215                 return tmc_enable_etr_sink_perf(csdev, mode);
216         }
217
218         /* We shouldn't be here */
219         return -EINVAL;
220 }
221
222 static void tmc_disable_etr_sink(struct coresight_device *csdev)
223 {
224         long val;
225         unsigned long flags;
226         struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
227
228         spin_lock_irqsave(&drvdata->spinlock, flags);
229         if (drvdata->reading) {
230                 spin_unlock_irqrestore(&drvdata->spinlock, flags);
231                 return;
232         }
233
234         val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
235         /* Disable the TMC only if it needs to */
236         if (val != CS_MODE_DISABLED)
237                 tmc_etr_disable_hw(drvdata);
238
239         spin_unlock_irqrestore(&drvdata->spinlock, flags);
240
241         dev_info(drvdata->dev, "TMC-ETR disabled\n");
242 }
243
244 static const struct coresight_ops_sink tmc_etr_sink_ops = {
245         .enable         = tmc_enable_etr_sink,
246         .disable        = tmc_disable_etr_sink,
247 };
248
249 const struct coresight_ops tmc_etr_cs_ops = {
250         .sink_ops       = &tmc_etr_sink_ops,
251 };
252
253 int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
254 {
255         int ret = 0;
256         long val;
257         unsigned long flags;
258
259         /* config types are set a boot time and never change */
260         if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
261                 return -EINVAL;
262
263         spin_lock_irqsave(&drvdata->spinlock, flags);
264         if (drvdata->reading) {
265                 ret = -EBUSY;
266                 goto out;
267         }
268
269         val = local_read(&drvdata->mode);
270         /* Don't interfere if operated from Perf */
271         if (val == CS_MODE_PERF) {
272                 ret = -EINVAL;
273                 goto out;
274         }
275
276         /* If drvdata::buf is NULL the trace data has been read already */
277         if (drvdata->buf == NULL) {
278                 ret = -EINVAL;
279                 goto out;
280         }
281
282         /* Disable the TMC if need be */
283         if (val == CS_MODE_SYSFS)
284                 tmc_etr_disable_hw(drvdata);
285
286         drvdata->reading = true;
287 out:
288         spin_unlock_irqrestore(&drvdata->spinlock, flags);
289
290         return ret;
291 }
292
293 int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
294 {
295         unsigned long flags;
296         dma_addr_t paddr;
297         void __iomem *vaddr = NULL;
298
299         /* config types are set a boot time and never change */
300         if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
301                 return -EINVAL;
302
303         spin_lock_irqsave(&drvdata->spinlock, flags);
304
305         /* RE-enable the TMC if need be */
306         if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
307                 /*
308                  * The trace run will continue with the same allocated trace
309                  * buffer. The trace buffer is cleared in tmc_etr_enable_hw(),
310                  * so we don't have to explicitly clear it. Also, since the
311                  * tracer is still enabled drvdata::buf can't be NULL.
312                  */
313                 tmc_etr_enable_hw(drvdata);
314         } else {
315                 /*
316                  * The ETR is not tracing and the buffer was just read.
317                  * As such prepare to free the trace buffer.
318                  */
319                 vaddr = drvdata->vaddr;
320                 paddr = drvdata->paddr;
321                 drvdata->buf = drvdata->vaddr = NULL;
322         }
323
324         drvdata->reading = false;
325         spin_unlock_irqrestore(&drvdata->spinlock, flags);
326
327         /* Free allocated memory out side of the spinlock */
328         if (vaddr)
329                 dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
330
331         return 0;
332 }