aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig.debug8
-rw-r--r--drivers/coresight/Makefile1
-rw-r--r--drivers/coresight/coresight-etb10.c537
3 files changed, 546 insertions, 0 deletions
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 4815efbbb55d..db6717079e31 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1368,5 +1368,13 @@ config CORESIGHT_SINK_TPIU
1368 for bridging the gap between the on-chip coresight components and a trace 1368 for bridging the gap between the on-chip coresight components and a trace
1369 port collection engine, typically connected to an external host for use 1369 port collection engine, typically connected to an external host for use
1370 case capturing more traces than the on-board coresight memory can handle. 1370 case capturing more traces than the on-board coresight memory can handle.
1371
1372config CORESIGHT_SINK_ETBV10
1373 bool "Coresight ETBv1.0 driver"
1374 depends on CORESIGHT_LINKS_AND_SINKS
1375 help
1376 This enables support for the Embedded Trace Buffer version 1.0 driver
1377 that complies with the generic implementation of the component without
1378 special enhancement or added features.
1371endif 1379endif
1372endmenu 1380endmenu
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 41ab769b4822..4c43dade4c14 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_CORESIGHT) += coresight.o
5obj-$(CONFIG_OF) += of_coresight.o 5obj-$(CONFIG_OF) += of_coresight.o
6obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o 6obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
7obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o 7obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
8obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
diff --git a/drivers/coresight/coresight-etb10.c b/drivers/coresight/coresight-etb10.c
new file mode 100644
index 000000000000..c922d4aded8a
--- /dev/null
+++ b/drivers/coresight/coresight-etb10.c
@@ -0,0 +1,537 @@
1/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/device.h>
18#include <linux/io.h>
19#include <linux/err.h>
20#include <linux/fs.h>
21#include <linux/miscdevice.h>
22#include <linux/uaccess.h>
23#include <linux/slab.h>
24#include <linux/spinlock.h>
25#include <linux/clk.h>
26#include <linux/seq_file.h>
27#include <linux/coresight.h>
28#include <linux/amba/bus.h>
29
30#include "coresight-priv.h"
31
32#define ETB_RAM_DEPTH_REG 0x004
33#define ETB_STATUS_REG 0x00c
34#define ETB_RAM_READ_DATA_REG 0x010
35#define ETB_RAM_READ_POINTER 0x014
36#define ETB_RAM_WRITE_POINTER 0x018
37#define ETB_TRG 0x01c
38#define ETB_CTL_REG 0x020
39#define ETB_RWD_REG 0x024
40#define ETB_FFSR 0x300
41#define ETB_FFCR 0x304
42#define ETB_ITMISCOP0 0xee0
43#define ETB_ITTRFLINACK 0xee4
44#define ETB_ITTRFLIN 0xee8
45#define ETB_ITATBDATA0 0xeeC
46#define ETB_ITATBCTR2 0xef0
47#define ETB_ITATBCTR1 0xef4
48#define ETB_ITATBCTR0 0xef8
49
50/* register description */
51/* STS - 0x00C */
52#define ETB_STATUS_RAM_FULL BIT(0)
53/* CTL - 0x020 */
54#define ETB_CTL_CAPT_EN BIT(0)
55/* FFCR - 0x304 */
56#define ETB_FFCR_EN_FTC BIT(0)
57#define ETB_FFCR_FON_MAN BIT(6)
58#define ETB_FFCR_STOP_FI BIT(12)
59#define ETB_FFCR_STOP_TRIGGER BIT(13)
60
61#define ETB_FFCR_BIT 6
62#define ETB_FFSR_BIT 1
63#define ETB_FRAME_SIZE_WORDS 4
64
65/**
66 * struct etb_drvdata - specifics associated to an ETB component
67 * @base: memory mapped base address for this component.
68 * @dev: the device entity associated to this component.
69 * @csdev: component vitals needed by the framework.
70 * @miscdev: specifics to handle "/dev/xyz.etb" entry.
71 * @clk: the clock this component is associated to.
72 * @spinlock: only one at a time pls.
73 * @in_use: synchronise user space access to etb buffer.
74 * @buf: area of memory where ETB buffer content gets sent.
75 * @buffer_depth: size of @buf.
76 * @enable: this ETB is being used.
77 * @trigger_cntr: amount of words to store after a trigger.
78 */
79struct etb_drvdata {
80 void __iomem *base;
81 struct device *dev;
82 struct coresight_device *csdev;
83 struct miscdevice miscdev;
84 struct clk *clk;
85 spinlock_t spinlock;
86 atomic_t in_use;
87 u8 *buf;
88 u32 buffer_depth;
89 bool enable;
90 u32 trigger_cntr;
91};
92
93static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
94{
95 int ret;
96 u32 depth = 0;
97
98 ret = clk_prepare_enable(drvdata->clk);
99 if (ret)
100 return ret;
101
102 /* RO registers don't need locking */
103 depth = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
104
105 clk_disable_unprepare(drvdata->clk);
106 return depth;
107}
108
109static void etb_enable_hw(struct etb_drvdata *drvdata)
110{
111 int i;
112 u32 depth;
113
114 CS_UNLOCK(drvdata->base);
115
116 depth = drvdata->buffer_depth;
117 /* reset write RAM pointer address */
118 writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER);
119 /* clear entire RAM buffer */
120 for (i = 0; i < depth; i++)
121 writel_relaxed(0x0, drvdata->base + ETB_RWD_REG);
122
123 /* reset write RAM pointer address */
124 writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER);
125 /* reset read RAM pointer address */
126 writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER);
127
128 writel_relaxed(drvdata->trigger_cntr, drvdata->base + ETB_TRG);
129 writel_relaxed(ETB_FFCR_EN_FTC | ETB_FFCR_STOP_TRIGGER,
130 drvdata->base + ETB_FFCR);
131 /* ETB trace capture enable */
132 writel_relaxed(ETB_CTL_CAPT_EN, drvdata->base + ETB_CTL_REG);
133
134 CS_LOCK(drvdata->base);
135}
136
137static int etb_enable(struct coresight_device *csdev)
138{
139 struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
140 int ret;
141 unsigned long flags;
142
143 ret = clk_prepare_enable(drvdata->clk);
144 if (ret)
145 return ret;
146
147 spin_lock_irqsave(&drvdata->spinlock, flags);
148 etb_enable_hw(drvdata);
149 drvdata->enable = true;
150 spin_unlock_irqrestore(&drvdata->spinlock, flags);
151
152 dev_info(drvdata->dev, "ETB enabled\n");
153 return 0;
154}
155
156static void etb_disable_hw(struct etb_drvdata *drvdata)
157{
158 u32 ffcr;
159
160 CS_UNLOCK(drvdata->base);
161
162 ffcr = readl_relaxed(drvdata->base + ETB_FFCR);
163 /* stop formatter when a stop has completed */
164 ffcr |= ETB_FFCR_STOP_FI;
165 writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
166 /* manually generate a flush of the system */
167 ffcr |= ETB_FFCR_FON_MAN;
168 writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
169
170 if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
171 dev_err(drvdata->dev,
172 "timeout observed when probing at offset %#x\n",
173 ETB_FFCR);
174 }
175
176 /* disable trace capture */
177 writel_relaxed(0x0, drvdata->base + ETB_CTL_REG);
178
179 if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
180 dev_err(drvdata->dev,
181 "timeout observed when probing at offset %#x\n",
182 ETB_FFCR);
183 }
184
185 CS_LOCK(drvdata->base);
186}
187
188static void etb_dump_hw(struct etb_drvdata *drvdata)
189{
190 int i;
191 u8 *buf_ptr;
192 u32 read_data, depth;
193 u32 read_ptr, write_ptr;
194 u32 frame_off, frame_endoff;
195
196 CS_UNLOCK(drvdata->base);
197
198 read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
199 write_ptr = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
200
201 frame_off = write_ptr % ETB_FRAME_SIZE_WORDS;
202 frame_endoff = ETB_FRAME_SIZE_WORDS - frame_off;
203 if (frame_off) {
204 dev_err(drvdata->dev,
205 "write_ptr: %lu not aligned to formatter frame size\n",
206 (unsigned long)write_ptr);
207 dev_err(drvdata->dev, "frameoff: %lu, frame_endoff: %lu\n",
208 (unsigned long)frame_off, (unsigned long)frame_endoff);
209 write_ptr += frame_endoff;
210 }
211
212 if ((readl_relaxed(drvdata->base + ETB_STATUS_REG)
213 & ETB_STATUS_RAM_FULL) == 0)
214 writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER);
215 else
216 writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER);
217
218 depth = drvdata->buffer_depth;
219 buf_ptr = drvdata->buf;
220 for (i = 0; i < depth; i++) {
221 read_data = readl_relaxed(drvdata->base +
222 ETB_RAM_READ_DATA_REG);
223 *buf_ptr++ = read_data >> 0;
224 *buf_ptr++ = read_data >> 8;
225 *buf_ptr++ = read_data >> 16;
226 *buf_ptr++ = read_data >> 24;
227 }
228
229 if (frame_off) {
230 buf_ptr -= (frame_endoff * 4);
231 for (i = 0; i < frame_endoff; i++) {
232 *buf_ptr++ = 0x0;
233 *buf_ptr++ = 0x0;
234 *buf_ptr++ = 0x0;
235 *buf_ptr++ = 0x0;
236 }
237 }
238
239 writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER);
240
241 CS_LOCK(drvdata->base);
242}
243
244static void etb_disable(struct coresight_device *csdev)
245{
246 struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
247 unsigned long flags;
248
249 spin_lock_irqsave(&drvdata->spinlock, flags);
250 etb_disable_hw(drvdata);
251 etb_dump_hw(drvdata);
252 drvdata->enable = false;
253 spin_unlock_irqrestore(&drvdata->spinlock, flags);
254
255 clk_disable_unprepare(drvdata->clk);
256
257 dev_info(drvdata->dev, "ETB disabled\n");
258}
259
260static const struct coresight_ops_sink etb_sink_ops = {
261 .enable = etb_enable,
262 .disable = etb_disable,
263};
264
265static const struct coresight_ops etb_cs_ops = {
266 .sink_ops = &etb_sink_ops,
267};
268
269static void etb_dump(struct etb_drvdata *drvdata)
270{
271 unsigned long flags;
272
273 spin_lock_irqsave(&drvdata->spinlock, flags);
274 if (drvdata->enable) {
275 etb_disable_hw(drvdata);
276 etb_dump_hw(drvdata);
277 etb_enable_hw(drvdata);
278 }
279 spin_unlock_irqrestore(&drvdata->spinlock, flags);
280
281 dev_info(drvdata->dev, "ETB dumped\n");
282}
283
284static int etb_open(struct inode *inode, struct file *file)
285{
286 struct etb_drvdata *drvdata = container_of(file->private_data,
287 struct etb_drvdata, miscdev);
288
289 if (atomic_cmpxchg(&drvdata->in_use, 0, 1))
290 return -EBUSY;
291
292 dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
293 return 0;
294}
295
296static ssize_t etb_read(struct file *file, char __user *data,
297 size_t len, loff_t *ppos)
298{
299 u32 depth;
300 struct etb_drvdata *drvdata = container_of(file->private_data,
301 struct etb_drvdata, miscdev);
302
303 etb_dump(drvdata);
304
305 depth = drvdata->buffer_depth;
306 if (*ppos + len > depth * 4)
307 len = depth * 4 - *ppos;
308
309 if (copy_to_user(data, drvdata->buf + *ppos, len)) {
310 dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
311 return -EFAULT;
312 }
313
314 *ppos += len;
315
316 dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
317 __func__, len, (int) (depth * 4 - *ppos));
318 return len;
319}
320
321static int etb_release(struct inode *inode, struct file *file)
322{
323 struct etb_drvdata *drvdata = container_of(file->private_data,
324 struct etb_drvdata, miscdev);
325 atomic_set(&drvdata->in_use, 0);
326
327 dev_dbg(drvdata->dev, "%s: released\n", __func__);
328 return 0;
329}
330
331static const struct file_operations etb_fops = {
332 .owner = THIS_MODULE,
333 .open = etb_open,
334 .read = etb_read,
335 .release = etb_release,
336 .llseek = no_llseek,
337};
338
339static ssize_t status_show(struct device *dev,
340 struct device_attribute *attr, char *buf)
341{
342 int ret;
343 unsigned long flags;
344 u32 etb_rdr, etb_sr, etb_rrp, etb_rwp;
345 u32 etb_trg, etb_cr, etb_ffsr, etb_ffcr;
346 struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
347
348 ret = clk_prepare_enable(drvdata->clk);
349 if (ret)
350 goto out;
351
352 spin_lock_irqsave(&drvdata->spinlock, flags);
353 CS_UNLOCK(drvdata->base);
354
355 etb_rdr = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
356 etb_sr = readl_relaxed(drvdata->base + ETB_STATUS_REG);
357 etb_rrp = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
358 etb_rwp = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
359 etb_trg = readl_relaxed(drvdata->base + ETB_TRG);
360 etb_cr = readl_relaxed(drvdata->base + ETB_CTL_REG);
361 etb_ffsr = readl_relaxed(drvdata->base + ETB_FFSR);
362 etb_ffcr = readl_relaxed(drvdata->base + ETB_FFCR);
363
364 CS_LOCK(drvdata->base);
365 spin_unlock_irqrestore(&drvdata->spinlock, flags);
366
367 clk_disable_unprepare(drvdata->clk);
368
369 return sprintf(buf,
370 "Depth:\t\t0x%x\n"
371 "Status:\t\t0x%x\n"
372 "RAM read ptr:\t0x%x\n"
373 "RAM wrt ptr:\t0x%x\n"
374 "Trigger cnt:\t0x%x\n"
375 "Control:\t0x%x\n"
376 "Flush status:\t0x%x\n"
377 "Flush ctrl:\t0x%x\n",
378 etb_rdr, etb_sr, etb_rrp, etb_rwp,
379 etb_trg, etb_cr, etb_ffsr, etb_ffcr);
380out:
381 return -EINVAL;
382}
383static DEVICE_ATTR_RO(status);
384
385static ssize_t trigger_cntr_show(struct device *dev,
386 struct device_attribute *attr, char *buf)
387{
388 struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
389 unsigned long val = drvdata->trigger_cntr;
390
391 return sprintf(buf, "%#lx\n", val);
392}
393
394static ssize_t trigger_cntr_store(struct device *dev,
395 struct device_attribute *attr,
396 const char *buf, size_t size)
397{
398 int ret;
399 unsigned long val;
400 struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
401
402 ret = kstrtoul(buf, 16, &val);
403 if (ret)
404 return ret;
405
406 drvdata->trigger_cntr = val;
407 return size;
408}
409static DEVICE_ATTR_RW(trigger_cntr);
410
411static struct attribute *coresight_etb_attrs[] = {
412 &dev_attr_trigger_cntr.attr,
413 &dev_attr_status.attr,
414 NULL,
415};
416ATTRIBUTE_GROUPS(coresight_etb);
417
418static int etb_probe(struct amba_device *adev, const struct amba_id *id)
419{
420 int ret;
421 void __iomem *base;
422 struct device *dev = &adev->dev;
423 struct coresight_platform_data *pdata = NULL;
424 struct etb_drvdata *drvdata;
425 struct resource *res = &adev->res;
426 struct coresight_desc *desc;
427 struct device_node *np = adev->dev.of_node;
428
429 if (np) {
430 pdata = of_get_coresight_platform_data(dev, np);
431 if (IS_ERR(pdata))
432 return PTR_ERR(pdata);
433 adev->dev.platform_data = pdata;
434 }
435
436 drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
437 if (!drvdata)
438 return -ENOMEM;
439
440 drvdata->dev = &adev->dev;
441 dev_set_drvdata(dev, drvdata);
442
443 /* validity for the resource is already checked by the AMBA core */
444 base = devm_ioremap_resource(dev, res);
445 if (IS_ERR(base))
446 return PTR_ERR(base);
447
448 drvdata->base = base;
449
450 spin_lock_init(&drvdata->spinlock);
451
452 drvdata->clk = adev->pclk;
453 ret = clk_prepare_enable(drvdata->clk);
454 if (ret)
455 return ret;
456
457 drvdata->buffer_depth = etb_get_buffer_depth(drvdata);
458 clk_disable_unprepare(drvdata->clk);
459
460 if (drvdata->buffer_depth < 0)
461 return -EINVAL;
462
463 drvdata->buf = devm_kzalloc(dev,
464 drvdata->buffer_depth * 4, GFP_KERNEL);
465 if (!drvdata->buf)
466 return -ENOMEM;
467
468 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
469 if (!desc)
470 return -ENOMEM;
471
472 desc->type = CORESIGHT_DEV_TYPE_SINK;
473 desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
474 desc->ops = &etb_cs_ops;
475 desc->pdata = pdata;
476 desc->dev = dev;
477 desc->groups = coresight_etb_groups;
478 drvdata->csdev = coresight_register(desc);
479 if (IS_ERR(drvdata->csdev))
480 return PTR_ERR(drvdata->csdev);
481
482 drvdata->miscdev.name = pdata->name;
483 drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
484 drvdata->miscdev.fops = &etb_fops;
485 ret = misc_register(&drvdata->miscdev);
486 if (ret)
487 goto err_misc_register;
488
489 dev_info(dev, "ETB initialized\n");
490 return 0;
491
492err_misc_register:
493 coresight_unregister(drvdata->csdev);
494 return ret;
495}
496
497static int etb_remove(struct amba_device *adev)
498{
499 struct etb_drvdata *drvdata = amba_get_drvdata(adev);
500
501 misc_deregister(&drvdata->miscdev);
502 coresight_unregister(drvdata->csdev);
503 return 0;
504}
505
506static struct amba_id etb_ids[] = {
507 {
508 .id = 0x0003b907,
509 .mask = 0x0003ffff,
510 },
511 { 0, 0},
512};
513
514static struct amba_driver etb_driver = {
515 .drv = {
516 .name = "coresight-etb10",
517 .owner = THIS_MODULE,
518 },
519 .probe = etb_probe,
520 .remove = etb_remove,
521 .id_table = etb_ids,
522};
523
524static int __init etb_init(void)
525{
526 return amba_driver_register(&etb_driver);
527}
528module_init(etb_init);
529
530static void __exit etb_exit(void)
531{
532 amba_driver_unregister(&etb_driver);
533}
534module_exit(etb_exit);
535
536MODULE_LICENSE("GPL v2");
537MODULE_DESCRIPTION("CoreSight Embedded Trace Buffer driver");