blob: 886ea83c68e0cf2233398f46cb00edbe188c56b6 [file] [log] [blame]
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -06001/*
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>
Mathieu Poirierde546192016-05-03 11:33:52 -060019#include <linux/dma-mapping.h>
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -060020#include "coresight-priv.h"
21#include "coresight-tmc.h"
22
Baoyou Xie0ef75282016-09-08 16:50:39 -060023static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -060024{
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
60static 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
Suzuki K Poulose8505fea2016-08-25 15:18:57 -060067 /*
68 * Adjust the buffer to point to the beginning of the trace data
69 * and update the available trace data.
70 */
Suzuki K Poulose1c9cbe12016-08-25 15:18:59 -060071 if (val & TMC_STS_FULL) {
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -060072 drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
Suzuki K Poulose8505fea2016-08-25 15:18:57 -060073 drvdata->len = drvdata->size;
74 } else {
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -060075 drvdata->buf = drvdata->vaddr;
Suzuki K Poulose8505fea2016-08-25 15:18:57 -060076 drvdata->len = rwp - drvdata->paddr;
77 }
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -060078}
79
Mathieu Poirier45254122016-05-03 11:33:51 -060080static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -060081{
82 CS_UNLOCK(drvdata->base);
83
84 tmc_flush_and_stop(drvdata);
Mathieu Poiriera40318f2016-05-03 11:33:55 -060085 /*
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);
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -060091 tmc_disable_hw(drvdata);
92
93 CS_LOCK(drvdata->base);
94}
95
Mathieu Poirierb2176012016-05-03 11:33:56 -060096static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -060097{
Mathieu Poirierde546192016-05-03 11:33:52 -060098 int ret = 0;
99 bool used = false;
Mathieu Poirierf2facc32016-05-03 11:33:54 -0600100 long val;
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600101 unsigned long flags;
Mathieu Poirierde546192016-05-03 11:33:52 -0600102 void __iomem *vaddr = NULL;
103 dma_addr_t paddr;
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600104 struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
105
Mathieu Poirierde546192016-05-03 11:33:52 -0600106 /* 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 */
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600114 spin_lock_irqsave(&drvdata->spinlock, flags);
Mathieu Poirierde546192016-05-03 11:33:52 -0600115 if (!drvdata->vaddr) {
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600116 spin_unlock_irqrestore(&drvdata->spinlock, flags);
Mathieu Poirierde546192016-05-03 11:33:52 -0600117
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);
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600130 }
131
Mathieu Poirierde546192016-05-03 11:33:52 -0600132 if (drvdata->reading) {
133 ret = -EBUSY;
134 goto out;
135 }
136
Mathieu Poirierf2facc32016-05-03 11:33:54 -0600137 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
Mathieu Poirierde546192016-05-03 11:33:52 -0600146 /*
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
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600160 tmc_etr_enable_hw(drvdata);
Mathieu Poirierde546192016-05-03 11:33:52 -0600161out:
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600162 spin_unlock_irqrestore(&drvdata->spinlock, flags);
163
Mathieu Poirierde546192016-05-03 11:33:52 -0600164 /* 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;
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600172}
173
Mathieu Poirierb2176012016-05-03 11:33:56 -0600174static 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);
203out:
204 spin_unlock_irqrestore(&drvdata->spinlock, flags);
205
206 return ret;
207}
208
209static 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
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600222static void tmc_disable_etr_sink(struct coresight_device *csdev)
223{
Mathieu Poirierf2facc32016-05-03 11:33:54 -0600224 long val;
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600225 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
Mathieu Poirierf2facc32016-05-03 11:33:54 -0600234 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
Mathieu Poirier6c6ed1e2016-05-03 11:33:50 -0600239 spin_unlock_irqrestore(&drvdata->spinlock, flags);
240
241 dev_info(drvdata->dev, "TMC-ETR disabled\n");
242}
243
244static const struct coresight_ops_sink tmc_etr_sink_ops = {
245 .enable = tmc_enable_etr_sink,
246 .disable = tmc_disable_etr_sink,
247};
248
249const struct coresight_ops tmc_etr_cs_ops = {
250 .sink_ops = &tmc_etr_sink_ops,
251};
Mathieu Poirier45254122016-05-03 11:33:51 -0600252
253int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
254{
Mathieu Poirierde546192016-05-03 11:33:52 -0600255 int ret = 0;
Mathieu Poirierb2176012016-05-03 11:33:56 -0600256 long val;
Mathieu Poirier45254122016-05-03 11:33:51 -0600257 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);
Mathieu Poirierf74debb2016-05-03 11:33:53 -0600264 if (drvdata->reading) {
265 ret = -EBUSY;
266 goto out;
267 }
Mathieu Poirier45254122016-05-03 11:33:51 -0600268
Mathieu Poirierb2176012016-05-03 11:33:56 -0600269 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
Mathieu Poirierde546192016-05-03 11:33:52 -0600276 /* 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
Mathieu Poirier45254122016-05-03 11:33:51 -0600282 /* Disable the TMC if need be */
Mathieu Poirierb2176012016-05-03 11:33:56 -0600283 if (val == CS_MODE_SYSFS)
Mathieu Poirier45254122016-05-03 11:33:51 -0600284 tmc_etr_disable_hw(drvdata);
285
286 drvdata->reading = true;
Mathieu Poirierde546192016-05-03 11:33:52 -0600287out:
Mathieu Poirier45254122016-05-03 11:33:51 -0600288 spin_unlock_irqrestore(&drvdata->spinlock, flags);
289
Mathieu Poirierb2176012016-05-03 11:33:56 -0600290 return ret;
Mathieu Poirier45254122016-05-03 11:33:51 -0600291}
292
293int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
294{
295 unsigned long flags;
Mathieu Poirierde546192016-05-03 11:33:52 -0600296 dma_addr_t paddr;
297 void __iomem *vaddr = NULL;
Mathieu Poirier45254122016-05-03 11:33:51 -0600298
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 */
Mathieu Poirierf2facc32016-05-03 11:33:54 -0600306 if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
Mathieu Poirierde546192016-05-03 11:33:52 -0600307 /*
308 * The trace run will continue with the same allocated trace
Suzuki K Poulosef3b81722016-06-14 11:17:14 -0600309 * 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.
Mathieu Poirierde546192016-05-03 11:33:52 -0600312 */
Mathieu Poirier45254122016-05-03 11:33:51 -0600313 tmc_etr_enable_hw(drvdata);
Mathieu Poirierde546192016-05-03 11:33:52 -0600314 } 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;
Suzuki K Poulose8e215292016-06-14 11:17:13 -0600321 drvdata->buf = drvdata->vaddr = NULL;
Mathieu Poirierde546192016-05-03 11:33:52 -0600322 }
Mathieu Poirier45254122016-05-03 11:33:51 -0600323
324 drvdata->reading = false;
325 spin_unlock_irqrestore(&drvdata->spinlock, flags);
326
Mathieu Poirierde546192016-05-03 11:33:52 -0600327 /* Free allocated memory out side of the spinlock */
328 if (vaddr)
329 dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
330
Mathieu Poirier45254122016-05-03 11:33:51 -0600331 return 0;
332}