coresight: Add helper for inserting synchronization packets
[linux-2.6-block.git] / drivers / hwtracing / coresight / coresight-tmc.c
CommitLineData
ad0dfdfd 1// SPDX-License-Identifier: GPL-2.0
bc4bf7fe 2/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
941943cf
PG
3 *
4 * Description: CoreSight Trace Memory Controller driver
bc4bf7fe
PP
5 */
6
7#include <linux/kernel.h>
bc4bf7fe
PP
8#include <linux/init.h>
9#include <linux/types.h>
10#include <linux/device.h>
11#include <linux/io.h>
12#include <linux/err.h>
13#include <linux/fs.h>
14#include <linux/miscdevice.h>
15#include <linux/uaccess.h>
16#include <linux/slab.h>
17#include <linux/dma-mapping.h>
18#include <linux/spinlock.h>
32398ef6 19#include <linux/pm_runtime.h>
bc4bf7fe
PP
20#include <linux/of.h>
21#include <linux/coresight.h>
22#include <linux/amba/bus.h>
23
24#include "coresight-priv.h"
4c324b5f 25#include "coresight-tmc.h"
bc4bf7fe 26
6c6ed1e2 27void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
bc4bf7fe
PP
28{
29 /* Ensure formatter, unformatter and hardware fifo are empty */
30 if (coresight_timeout(drvdata->base,
580ff804 31 TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
bc4bf7fe 32 dev_err(drvdata->dev,
67337e8d 33 "timeout while waiting for TMC to be Ready\n");
bc4bf7fe
PP
34 }
35}
36
6c6ed1e2 37void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
bc4bf7fe
PP
38{
39 u32 ffcr;
40
41 ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
42 ffcr |= TMC_FFCR_STOP_ON_FLUSH;
43 writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
a8ab4268 44 ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT);
bc4bf7fe
PP
45 writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
46 /* Ensure flush completes */
47 if (coresight_timeout(drvdata->base,
48 TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
49 dev_err(drvdata->dev,
67337e8d 50 "timeout while waiting for completion of Manual Flush\n");
bc4bf7fe
PP
51 }
52
580ff804 53 tmc_wait_for_tmcready(drvdata);
bc4bf7fe
PP
54}
55
6c6ed1e2 56void tmc_enable_hw(struct tmc_drvdata *drvdata)
bc4bf7fe
PP
57{
58 writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
59}
60
6c6ed1e2 61void tmc_disable_hw(struct tmc_drvdata *drvdata)
bc4bf7fe
PP
62{
63 writel_relaxed(0x0, drvdata->base + TMC_CTL);
64}
65
bc4bf7fe
PP
66static int tmc_read_prepare(struct tmc_drvdata *drvdata)
67{
b1789b79 68 int ret = 0;
bc4bf7fe 69
b1789b79
MP
70 switch (drvdata->config_type) {
71 case TMC_CONFIG_TYPE_ETB:
b1789b79 72 case TMC_CONFIG_TYPE_ETF:
4525412a 73 ret = tmc_read_prepare_etb(drvdata);
b1789b79
MP
74 break;
75 case TMC_CONFIG_TYPE_ETR:
4525412a 76 ret = tmc_read_prepare_etr(drvdata);
b1789b79
MP
77 break;
78 default:
79 ret = -EINVAL;
bc4bf7fe 80 }
b1789b79 81
4525412a
MP
82 if (!ret)
83 dev_info(drvdata->dev, "TMC read start\n");
84
bc4bf7fe
PP
85 return ret;
86}
87
f74debbe 88static int tmc_read_unprepare(struct tmc_drvdata *drvdata)
bc4bf7fe 89{
4525412a 90 int ret = 0;
bc4bf7fe 91
b1789b79
MP
92 switch (drvdata->config_type) {
93 case TMC_CONFIG_TYPE_ETB:
b1789b79 94 case TMC_CONFIG_TYPE_ETF:
4525412a 95 ret = tmc_read_unprepare_etb(drvdata);
b1789b79
MP
96 break;
97 case TMC_CONFIG_TYPE_ETR:
4525412a 98 ret = tmc_read_unprepare_etr(drvdata);
b1789b79
MP
99 break;
100 default:
4525412a 101 ret = -EINVAL;
bc4bf7fe 102 }
b1789b79 103
4525412a
MP
104 if (!ret)
105 dev_info(drvdata->dev, "TMC read end\n");
f74debbe
MP
106
107 return ret;
bc4bf7fe
PP
108}
109
110static int tmc_open(struct inode *inode, struct file *file)
111{
f74debbe 112 int ret;
bc4bf7fe
PP
113 struct tmc_drvdata *drvdata = container_of(file->private_data,
114 struct tmc_drvdata, miscdev);
bc4bf7fe
PP
115
116 ret = tmc_read_prepare(drvdata);
117 if (ret)
118 return ret;
f74debbe 119
bc4bf7fe
PP
120 nonseekable_open(inode, file);
121
122 dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
123 return 0;
124}
125
3495722a
SP
126static inline ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata,
127 loff_t pos, size_t len, char **bufpp)
128{
129 switch (drvdata->config_type) {
130 case TMC_CONFIG_TYPE_ETB:
131 case TMC_CONFIG_TYPE_ETF:
132 return tmc_etb_get_sysfs_trace(drvdata, pos, len, bufpp);
133 case TMC_CONFIG_TYPE_ETR:
134 return tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp);
135 }
136
137 return -EINVAL;
138}
139
bc4bf7fe
PP
140static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
141 loff_t *ppos)
142{
3495722a
SP
143 char *bufp;
144 ssize_t actual;
bc4bf7fe
PP
145 struct tmc_drvdata *drvdata = container_of(file->private_data,
146 struct tmc_drvdata, miscdev);
3495722a
SP
147 actual = tmc_get_sysfs_trace(drvdata, *ppos, len, &bufp);
148 if (actual <= 0)
149 return 0;
bc4bf7fe 150
3495722a 151 if (copy_to_user(data, bufp, actual)) {
bc4bf7fe
PP
152 dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
153 return -EFAULT;
154 }
155
3495722a
SP
156 *ppos += actual;
157 dev_dbg(drvdata->dev, "%zu bytes copied\n", actual);
bc4bf7fe 158
3495722a 159 return actual;
bc4bf7fe
PP
160}
161
162static int tmc_release(struct inode *inode, struct file *file)
163{
f74debbe 164 int ret;
bc4bf7fe
PP
165 struct tmc_drvdata *drvdata = container_of(file->private_data,
166 struct tmc_drvdata, miscdev);
167
f74debbe
MP
168 ret = tmc_read_unprepare(drvdata);
169 if (ret)
170 return ret;
bc4bf7fe 171
bc4bf7fe
PP
172 dev_dbg(drvdata->dev, "%s: released\n", __func__);
173 return 0;
174}
175
176static const struct file_operations tmc_fops = {
177 .owner = THIS_MODULE,
178 .open = tmc_open,
179 .read = tmc_read,
180 .release = tmc_release,
181 .llseek = no_llseek,
182};
183
4f1ff3de
MP
184static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid)
185{
186 enum tmc_mem_intf_width memwidth;
187
188 /*
189 * Excerpt from the TRM:
190 *
191 * DEVID::MEMWIDTH[10:8]
192 * 0x2 Memory interface databus is 32 bits wide.
193 * 0x3 Memory interface databus is 64 bits wide.
194 * 0x4 Memory interface databus is 128 bits wide.
195 * 0x5 Memory interface databus is 256 bits wide.
196 */
197 switch (BMVAL(devid, 8, 10)) {
198 case 0x2:
199 memwidth = TMC_MEM_INTF_WIDTH_32BITS;
200 break;
201 case 0x3:
202 memwidth = TMC_MEM_INTF_WIDTH_64BITS;
203 break;
204 case 0x4:
205 memwidth = TMC_MEM_INTF_WIDTH_128BITS;
206 break;
207 case 0x5:
208 memwidth = TMC_MEM_INTF_WIDTH_256BITS;
209 break;
210 default:
211 memwidth = 0;
212 }
213
214 return memwidth;
215}
216
47675f6a
SP
217#define coresight_tmc_reg(name, offset) \
218 coresight_simple_reg32(struct tmc_drvdata, name, offset)
219#define coresight_tmc_reg64(name, lo_off, hi_off) \
220 coresight_simple_reg64(struct tmc_drvdata, name, lo_off, hi_off)
221
222coresight_tmc_reg(rsz, TMC_RSZ);
223coresight_tmc_reg(sts, TMC_STS);
224coresight_tmc_reg(trg, TMC_TRG);
225coresight_tmc_reg(ctl, TMC_CTL);
226coresight_tmc_reg(ffsr, TMC_FFSR);
227coresight_tmc_reg(ffcr, TMC_FFCR);
228coresight_tmc_reg(mode, TMC_MODE);
229coresight_tmc_reg(pscr, TMC_PSCR);
2b455339 230coresight_tmc_reg(axictl, TMC_AXICTL);
47675f6a
SP
231coresight_tmc_reg(devid, CORESIGHT_DEVID);
232coresight_tmc_reg64(rrp, TMC_RRP, TMC_RRPHI);
233coresight_tmc_reg64(rwp, TMC_RWP, TMC_RWPHI);
2b455339 234coresight_tmc_reg64(dba, TMC_DBALO, TMC_DBAHI);
7d83d177
MP
235
236static struct attribute *coresight_tmc_mgmt_attrs[] = {
237 &dev_attr_rsz.attr,
238 &dev_attr_sts.attr,
239 &dev_attr_rrp.attr,
240 &dev_attr_rwp.attr,
241 &dev_attr_trg.attr,
242 &dev_attr_ctl.attr,
243 &dev_attr_ffsr.attr,
244 &dev_attr_ffcr.attr,
245 &dev_attr_mode.attr,
246 &dev_attr_pscr.attr,
247 &dev_attr_devid.attr,
2b455339
SP
248 &dev_attr_dba.attr,
249 &dev_attr_axictl.attr,
7d83d177
MP
250 NULL,
251};
a2d6e184 252
0ef7528d
BX
253static ssize_t trigger_cntr_show(struct device *dev,
254 struct device_attribute *attr, char *buf)
bc4bf7fe
PP
255{
256 struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
257 unsigned long val = drvdata->trigger_cntr;
258
259 return sprintf(buf, "%#lx\n", val);
260}
261
262static ssize_t trigger_cntr_store(struct device *dev,
263 struct device_attribute *attr,
264 const char *buf, size_t size)
265{
266 int ret;
267 unsigned long val;
268 struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
269
270 ret = kstrtoul(buf, 16, &val);
271 if (ret)
272 return ret;
273
274 drvdata->trigger_cntr = val;
275 return size;
276}
277static DEVICE_ATTR_RW(trigger_cntr);
278
7d83d177 279static struct attribute *coresight_tmc_attrs[] = {
bc4bf7fe
PP
280 &dev_attr_trigger_cntr.attr,
281 NULL,
282};
bc4bf7fe 283
7d83d177
MP
284static const struct attribute_group coresight_tmc_group = {
285 .attrs = coresight_tmc_attrs,
bc4bf7fe 286};
bc4bf7fe 287
7d83d177
MP
288static const struct attribute_group coresight_tmc_mgmt_group = {
289 .attrs = coresight_tmc_mgmt_attrs,
290 .name = "mgmt",
291};
292
293const struct attribute_group *coresight_tmc_groups[] = {
294 &coresight_tmc_group,
295 &coresight_tmc_mgmt_group,
bc4bf7fe
PP
296 NULL,
297};
bc4bf7fe 298
2884132a
SP
299/* Detect and initialise the capabilities of a TMC ETR */
300static int tmc_etr_setup_caps(struct tmc_drvdata *drvdata,
301 u32 devid, void *dev_caps)
302{
ff11f5bc
SP
303 u32 dma_mask = 0;
304
2884132a
SP
305 /* Set the unadvertised capabilities */
306 tmc_etr_init_caps(drvdata, (u32)(unsigned long)dev_caps);
307
2e219345
SP
308 if (!(devid & TMC_DEVID_NOSCAT))
309 tmc_etr_set_cap(drvdata, TMC_ETR_SG);
ff11f5bc
SP
310
311 /* Check if the AXI address width is available */
312 if (devid & TMC_DEVID_AXIAW_VALID)
313 dma_mask = ((devid >> TMC_DEVID_AXIAW_SHIFT) &
314 TMC_DEVID_AXIAW_MASK);
315
2884132a 316 /*
ff11f5bc
SP
317 * Unless specified in the device configuration, ETR uses a 40-bit
318 * AXI master in place of the embedded SRAM of ETB/ETF.
2884132a 319 */
ff11f5bc
SP
320 switch (dma_mask) {
321 case 32:
322 case 40:
323 case 44:
324 case 48:
325 case 52:
326 dev_info(drvdata->dev, "Detected dma mask %dbits\n", dma_mask);
327 break;
328 default:
329 dma_mask = 40;
330 }
331
332 return dma_set_mask_and_coherent(drvdata->dev, DMA_BIT_MASK(dma_mask));
2884132a
SP
333}
334
bc4bf7fe
PP
335static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
336{
337 int ret = 0;
338 u32 devid;
339 void __iomem *base;
340 struct device *dev = &adev->dev;
341 struct coresight_platform_data *pdata = NULL;
342 struct tmc_drvdata *drvdata;
343 struct resource *res = &adev->res;
9486295a 344 struct coresight_desc desc = { 0 };
bc4bf7fe
PP
345 struct device_node *np = adev->dev.of_node;
346
347 if (np) {
348 pdata = of_get_coresight_platform_data(dev, np);
3afd0634
SP
349 if (IS_ERR(pdata)) {
350 ret = PTR_ERR(pdata);
351 goto out;
352 }
bc4bf7fe
PP
353 adev->dev.platform_data = pdata;
354 }
355
3afd0634 356 ret = -ENOMEM;
bc4bf7fe
PP
357 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
358 if (!drvdata)
3afd0634
SP
359 goto out;
360
bc4bf7fe
PP
361 drvdata->dev = &adev->dev;
362 dev_set_drvdata(dev, drvdata);
363
364 /* Validity for the resource is already checked by the AMBA core */
365 base = devm_ioremap_resource(dev, res);
3afd0634
SP
366 if (IS_ERR(base)) {
367 ret = PTR_ERR(base);
368 goto out;
369 }
bc4bf7fe
PP
370
371 drvdata->base = base;
372
373 spin_lock_init(&drvdata->spinlock);
374
bc4bf7fe
PP
375 devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
376 drvdata->config_type = BMVAL(devid, 6, 7);
4f1ff3de 377 drvdata->memwidth = tmc_get_memwidth(devid);
bc4bf7fe
PP
378
379 if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
380 if (np)
381 ret = of_property_read_u32(np,
382 "arm,buffer-size",
383 &drvdata->size);
384 if (ret)
385 drvdata->size = SZ_1M;
386 } else {
387 drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
388 }
389
32398ef6 390 pm_runtime_put(&adev->dev);
bc4bf7fe 391
9486295a
SP
392 desc.pdata = pdata;
393 desc.dev = dev;
394 desc.groups = coresight_tmc_groups;
bc4bf7fe 395
99ac6f12
SP
396 switch (drvdata->config_type) {
397 case TMC_CONFIG_TYPE_ETB:
9486295a
SP
398 desc.type = CORESIGHT_DEV_TYPE_SINK;
399 desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
400 desc.ops = &tmc_etb_cs_ops;
99ac6f12
SP
401 break;
402 case TMC_CONFIG_TYPE_ETR:
9486295a
SP
403 desc.type = CORESIGHT_DEV_TYPE_SINK;
404 desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
405 desc.ops = &tmc_etr_cs_ops;
2884132a 406 ret = tmc_etr_setup_caps(drvdata, devid, id->data);
a3959c50
RM
407 if (ret)
408 goto out;
99ac6f12
SP
409 break;
410 case TMC_CONFIG_TYPE_ETF:
9486295a
SP
411 desc.type = CORESIGHT_DEV_TYPE_LINKSINK;
412 desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
413 desc.ops = &tmc_etf_cs_ops;
99ac6f12
SP
414 break;
415 default:
416 pr_err("%s: Unsupported TMC config\n", pdata->name);
417 ret = -EINVAL;
418 goto out;
bc4bf7fe
PP
419 }
420
9486295a 421 drvdata->csdev = coresight_register(&desc);
bc4bf7fe
PP
422 if (IS_ERR(drvdata->csdev)) {
423 ret = PTR_ERR(drvdata->csdev);
3afd0634 424 goto out;
bc4bf7fe
PP
425 }
426
427 drvdata->miscdev.name = pdata->name;
428 drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
429 drvdata->miscdev.fops = &tmc_fops;
430 ret = misc_register(&drvdata->miscdev);
431 if (ret)
3afd0634
SP
432 coresight_unregister(drvdata->csdev);
433out:
bc4bf7fe
PP
434 return ret;
435}
436
6f964e7c 437static const struct amba_id tmc_ids[] = {
bc4bf7fe 438 {
0bbb194c
SP
439 .id = 0x000bb961,
440 .mask = 0x000fffff,
bc4bf7fe 441 },
6495892c
SP
442 {
443 /* Coresight SoC 600 TMC-ETR/ETS */
444 .id = 0x000bb9e8,
445 .mask = 0x000fffff,
446 .data = (void *)(unsigned long)CORESIGHT_SOC_600_ETR_CAPS,
447 },
448 {
449 /* Coresight SoC 600 TMC-ETB */
450 .id = 0x000bb9e9,
451 .mask = 0x000fffff,
452 },
453 {
454 /* Coresight SoC 600 TMC-ETF */
455 .id = 0x000bb9ea,
456 .mask = 0x000fffff,
457 },
bc4bf7fe
PP
458 { 0, 0},
459};
460
461static struct amba_driver tmc_driver = {
462 .drv = {
463 .name = "coresight-tmc",
464 .owner = THIS_MODULE,
b15f0fb6 465 .suppress_bind_attrs = true,
bc4bf7fe
PP
466 },
467 .probe = tmc_probe,
bc4bf7fe
PP
468 .id_table = tmc_ids,
469};
941943cf 470builtin_amba_driver(tmc_driver);