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