blob: a51bccca463ae72176e62251eb4c6bcce85f4137 [file] [log] [blame]
Alexander Shishkinc5d6c772009-12-01 14:00:51 +01001/*
2 * linux/arch/arm/kernel/etm.c
3 *
4 * Driver for ARM's Embedded Trace Macrocell and Embedded Trace Buffer.
5 *
6 * Copyright (C) 2009 Nokia Corporation.
7 * Alexander Shishkin
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/io.h>
18#include <linux/sysrq.h>
19#include <linux/device.h>
20#include <linux/clk.h>
21#include <linux/amba/bus.h>
22#include <linux/fs.h>
23#include <linux/uaccess.h>
24#include <linux/miscdevice.h>
25#include <linux/vmalloc.h>
26#include <linux/mutex.h>
Paul Gortmaker73017a52011-07-31 16:14:14 -040027#include <linux/module.h>
Alexander Shishkinc5d6c772009-12-01 14:00:51 +010028#include <asm/hardware/coresight.h>
29#include <asm/sections.h>
30
31MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Alexander Shishkin");
33
Alexander Shishkin8234eae2010-08-04 11:22:43 +010034/*
35 * ETM tracer state
36 */
37struct tracectx {
38 unsigned int etb_bufsz;
39 void __iomem *etb_regs;
40 void __iomem *etm_regs;
41 unsigned long flags;
42 int ncmppairs;
43 int etm_portsz;
44 struct device *dev;
45 struct clk *emu_clk;
46 struct mutex mutex;
47};
48
Alexander Shishkinc5d6c772009-12-01 14:00:51 +010049static struct tracectx tracer;
50
51static inline bool trace_isrunning(struct tracectx *t)
52{
53 return !!(t->flags & TRACER_RUNNING);
54}
55
56static int etm_setup_address_range(struct tracectx *t, int n,
57 unsigned long start, unsigned long end, int exclude, int data)
58{
Arve Hjønnevåg8511b5b2011-01-28 23:33:11 -080059 u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_IGNSECURITY |
Alexander Shishkinc5d6c772009-12-01 14:00:51 +010060 ETMAAT_NOVALCMP;
61
62 if (n < 1 || n > t->ncmppairs)
63 return -EINVAL;
64
65 /* comparators and ranges are numbered starting with 1 as opposed
66 * to bits in a word */
67 n--;
68
69 if (data)
70 flags |= ETMAAT_DLOADSTORE;
71 else
72 flags |= ETMAAT_IEXEC;
73
74 /* first comparator for the range */
75 etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2));
76 etm_writel(t, start, ETMR_COMP_VAL(n * 2));
77
78 /* second comparator is right next to it */
79 etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
80 etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1));
81
82 flags = exclude ? ETMTE_INCLEXCL : 0;
83 etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
84
85 return 0;
86}
87
88static int trace_start(struct tracectx *t)
89{
90 u32 v;
91 unsigned long timeout = TRACER_TIMEOUT;
92
93 etb_unlock(t);
94
Arve Hjønnevågf13ae472011-01-31 21:34:47 -080095 etb_writel(t, 0, ETBR_WRITEADDR);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +010096 etb_writel(t, 0, ETBR_FORMATTERCTRL);
97 etb_writel(t, 1, ETBR_CTRL);
98
99 etb_lock(t);
100
101 /* configure etm */
102 v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz);
103
104 if (t->flags & TRACER_CYCLE_ACC)
105 v |= ETMCTRL_CYCLEACCURATE;
106
107 etm_unlock(t);
108
109 etm_writel(t, v, ETMR_CTRL);
110
111 while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
112 ;
113 if (!timeout) {
114 dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
115 etm_lock(t);
116 return -EFAULT;
117 }
118
119 etm_setup_address_range(t, 1, (unsigned long)_stext,
120 (unsigned long)_etext, 0, 0);
121 etm_writel(t, 0, ETMR_TRACEENCTRL2);
122 etm_writel(t, 0, ETMR_TRACESSCTRL);
123 etm_writel(t, 0x6f, ETMR_TRACEENEVT);
124
125 v &= ~ETMCTRL_PROGRAM;
126 v |= ETMCTRL_PORTSEL;
127
128 etm_writel(t, v, ETMR_CTRL);
129
130 timeout = TRACER_TIMEOUT;
131 while (etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout)
132 ;
133 if (!timeout) {
134 dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n");
135 etm_lock(t);
136 return -EFAULT;
137 }
138
139 etm_lock(t);
140
141 t->flags |= TRACER_RUNNING;
142
143 return 0;
144}
145
146static int trace_stop(struct tracectx *t)
147{
148 unsigned long timeout = TRACER_TIMEOUT;
149
150 etm_unlock(t);
151
152 etm_writel(t, 0x440, ETMR_CTRL);
153 while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
154 ;
155 if (!timeout) {
156 dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
157 etm_lock(t);
158 return -EFAULT;
159 }
160
161 etm_lock(t);
162
163 etb_unlock(t);
164 etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL);
165
166 timeout = TRACER_TIMEOUT;
167 while (etb_readl(t, ETBR_FORMATTERCTRL) &
168 ETBFF_MANUAL_FLUSH && --timeout)
169 ;
170 if (!timeout) {
171 dev_dbg(t->dev, "Waiting for formatter flush to commence "
172 "timed out\n");
173 etb_lock(t);
174 return -EFAULT;
175 }
176
177 etb_writel(t, 0, ETBR_CTRL);
178
179 etb_lock(t);
180
181 t->flags &= ~TRACER_RUNNING;
182
183 return 0;
184}
185
186static int etb_getdatalen(struct tracectx *t)
187{
188 u32 v;
Arve Hjønnevågf13ae472011-01-31 21:34:47 -0800189 int wp;
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100190
191 v = etb_readl(t, ETBR_STATUS);
192
193 if (v & 1)
194 return t->etb_bufsz;
195
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100196 wp = etb_readl(t, ETBR_WRITEADDR);
Arve Hjønnevågf13ae472011-01-31 21:34:47 -0800197 return wp;
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100198}
199
200/* sysrq+v will always stop the running trace and leave it at that */
201static void etm_dump(void)
202{
203 struct tracectx *t = &tracer;
204 u32 first = 0;
205 int length;
206
207 if (!t->etb_regs) {
208 printk(KERN_INFO "No tracing hardware found\n");
209 return;
210 }
211
212 if (trace_isrunning(t))
213 trace_stop(t);
214
215 etb_unlock(t);
216
217 length = etb_getdatalen(t);
218
219 if (length == t->etb_bufsz)
220 first = etb_readl(t, ETBR_WRITEADDR);
221
222 etb_writel(t, first, ETBR_READADDR);
223
224 printk(KERN_INFO "Trace buffer contents length: %d\n", length);
225 printk(KERN_INFO "--- ETB buffer begin ---\n");
226 for (; length; length--)
227 printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM)));
228 printk(KERN_INFO "\n--- ETB buffer end ---\n");
229
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100230 etb_lock(t);
231}
232
Dmitry Torokhov1495cc92010-08-17 21:15:46 -0700233static void sysrq_etm_dump(int key)
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100234{
235 dev_dbg(tracer.dev, "Dumping ETB buffer\n");
236 etm_dump();
237}
238
239static struct sysrq_key_op sysrq_etm_op = {
240 .handler = sysrq_etm_dump,
241 .help_msg = "ETM buffer dump",
242 .action_msg = "etm",
243};
244
245static int etb_open(struct inode *inode, struct file *file)
246{
247 if (!tracer.etb_regs)
248 return -ENODEV;
249
250 file->private_data = &tracer;
251
252 return nonseekable_open(inode, file);
253}
254
255static ssize_t etb_read(struct file *file, char __user *data,
256 size_t len, loff_t *ppos)
257{
258 int total, i;
259 long length;
260 struct tracectx *t = file->private_data;
261 u32 first = 0;
262 u32 *buf;
Arve Hjønnevågf13ae472011-01-31 21:34:47 -0800263 int wpos;
264 int skip;
265 long wlength;
266 loff_t pos = *ppos;
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100267
268 mutex_lock(&t->mutex);
269
270 if (trace_isrunning(t)) {
271 length = 0;
272 goto out;
273 }
274
275 etb_unlock(t);
276
277 total = etb_getdatalen(t);
278 if (total == t->etb_bufsz)
279 first = etb_readl(t, ETBR_WRITEADDR);
280
Arve Hjønnevågf13ae472011-01-31 21:34:47 -0800281 if (pos > total * 4) {
282 skip = 0;
283 wpos = total;
284 } else {
285 skip = (int)pos % 4;
286 wpos = (int)pos / 4;
287 }
288 total -= wpos;
289 first = (first + wpos) % t->etb_bufsz;
290
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100291 etb_writel(t, first, ETBR_READADDR);
292
Arve Hjønnevågf13ae472011-01-31 21:34:47 -0800293 wlength = min(total, DIV_ROUND_UP(skip + (int)len, 4));
294 length = min(total * 4 - skip, (int)len);
295 buf = vmalloc(wlength * 4);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100296
Arve Hjønnevågf13ae472011-01-31 21:34:47 -0800297 dev_dbg(t->dev, "ETB read %ld bytes to %lld from %ld words at %d\n",
298 length, pos, wlength, first);
299 dev_dbg(t->dev, "ETB buffer length: %d\n", total + wpos);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100300 dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS));
Arve Hjønnevågf13ae472011-01-31 21:34:47 -0800301 for (i = 0; i < wlength; i++)
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100302 buf[i] = etb_readl(t, ETBR_READMEM);
303
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100304 etb_lock(t);
305
Arve Hjønnevågf13ae472011-01-31 21:34:47 -0800306 length -= copy_to_user(data, (u8 *)buf + skip, length);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100307 vfree(buf);
Arve Hjønnevågf13ae472011-01-31 21:34:47 -0800308 *ppos = pos + length;
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100309
310out:
311 mutex_unlock(&t->mutex);
312
313 return length;
314}
315
316static int etb_release(struct inode *inode, struct file *file)
317{
318 /* there's nothing to do here, actually */
319 return 0;
320}
321
322static const struct file_operations etb_fops = {
323 .owner = THIS_MODULE,
324 .read = etb_read,
325 .open = etb_open,
326 .release = etb_release,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200327 .llseek = no_llseek,
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100328};
329
330static struct miscdevice etb_miscdev = {
331 .name = "tracebuf",
332 .minor = 0,
333 .fops = &etb_fops,
334};
335
Ming Lei8e880692011-03-28 06:10:25 +0100336static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id)
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100337{
338 struct tracectx *t = &tracer;
339 int ret = 0;
340
341 ret = amba_request_regions(dev, NULL);
342 if (ret)
343 goto out;
344
345 t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
346 if (!t->etb_regs) {
347 ret = -ENOMEM;
348 goto out_release;
349 }
350
351 amba_set_drvdata(dev, t);
352
353 etb_miscdev.parent = &dev->dev;
354
355 ret = misc_register(&etb_miscdev);
356 if (ret)
357 goto out_unmap;
358
Arve Hjønnevågd3876592011-01-28 23:12:32 -0800359 /* Get optional clock. Currently used to select clock source on omap3 */
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100360 t->emu_clk = clk_get(&dev->dev, "emu_src_ck");
Arve Hjønnevågd3876592011-01-28 23:12:32 -0800361 if (IS_ERR(t->emu_clk))
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100362 dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n");
Arve Hjønnevågd3876592011-01-28 23:12:32 -0800363 else
364 clk_enable(t->emu_clk);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100365
366 etb_unlock(t);
367 t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
368 dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
369
370 /* make sure trace capture is disabled */
371 etb_writel(t, 0, ETBR_CTRL);
372 etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
373 etb_lock(t);
374
375 dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n");
376
377out:
378 return ret;
379
380out_unmap:
381 amba_set_drvdata(dev, NULL);
382 iounmap(t->etb_regs);
383
384out_release:
385 amba_release_regions(dev);
386
387 return ret;
388}
389
390static int etb_remove(struct amba_device *dev)
391{
392 struct tracectx *t = amba_get_drvdata(dev);
393
394 amba_set_drvdata(dev, NULL);
395
396 iounmap(t->etb_regs);
397 t->etb_regs = NULL;
398
Arve Hjønnevågd3876592011-01-28 23:12:32 -0800399 if (!IS_ERR(t->emu_clk)) {
400 clk_disable(t->emu_clk);
401 clk_put(t->emu_clk);
402 }
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100403
404 amba_release_regions(dev);
405
406 return 0;
407}
408
409static struct amba_id etb_ids[] = {
410 {
411 .id = 0x0003b907,
412 .mask = 0x0007ffff,
413 },
414 { 0, 0 },
415};
416
417static struct amba_driver etb_driver = {
418 .drv = {
419 .name = "etb",
420 .owner = THIS_MODULE,
421 },
422 .probe = etb_probe,
423 .remove = etb_remove,
424 .id_table = etb_ids,
425};
426
427/* use a sysfs file "trace_running" to start/stop tracing */
428static ssize_t trace_running_show(struct kobject *kobj,
429 struct kobj_attribute *attr,
430 char *buf)
431{
432 return sprintf(buf, "%x\n", trace_isrunning(&tracer));
433}
434
435static ssize_t trace_running_store(struct kobject *kobj,
436 struct kobj_attribute *attr,
437 const char *buf, size_t n)
438{
439 unsigned int value;
440 int ret;
441
442 if (sscanf(buf, "%u", &value) != 1)
443 return -EINVAL;
444
445 mutex_lock(&tracer.mutex);
446 ret = value ? trace_start(&tracer) : trace_stop(&tracer);
447 mutex_unlock(&tracer.mutex);
448
449 return ret ? : n;
450}
451
452static struct kobj_attribute trace_running_attr =
453 __ATTR(trace_running, 0644, trace_running_show, trace_running_store);
454
455static ssize_t trace_info_show(struct kobject *kobj,
456 struct kobj_attribute *attr,
457 char *buf)
458{
459 u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
460 int datalen;
461
462 etb_unlock(&tracer);
463 datalen = etb_getdatalen(&tracer);
464 etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
465 etb_ra = etb_readl(&tracer, ETBR_READADDR);
466 etb_st = etb_readl(&tracer, ETBR_STATUS);
467 etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
468 etb_lock(&tracer);
469
470 etm_unlock(&tracer);
471 etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
472 etm_st = etm_readl(&tracer, ETMR_STATUS);
473 etm_lock(&tracer);
474
475 return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
476 "ETBR_WRITEADDR:\t%08x\n"
477 "ETBR_READADDR:\t%08x\n"
478 "ETBR_STATUS:\t%08x\n"
479 "ETBR_FORMATTERCTRL:\t%08x\n"
480 "ETMR_CTRL:\t%08x\n"
481 "ETMR_STATUS:\t%08x\n",
482 datalen,
483 tracer.ncmppairs,
484 etb_wa,
485 etb_ra,
486 etb_st,
487 etb_fc,
488 etm_ctrl,
489 etm_st
490 );
491}
492
493static struct kobj_attribute trace_info_attr =
494 __ATTR(trace_info, 0444, trace_info_show, NULL);
495
496static ssize_t trace_mode_show(struct kobject *kobj,
497 struct kobj_attribute *attr,
498 char *buf)
499{
500 return sprintf(buf, "%d %d\n",
501 !!(tracer.flags & TRACER_CYCLE_ACC),
502 tracer.etm_portsz);
503}
504
505static ssize_t trace_mode_store(struct kobject *kobj,
506 struct kobj_attribute *attr,
507 const char *buf, size_t n)
508{
509 unsigned int cycacc, portsz;
510
511 if (sscanf(buf, "%u %u", &cycacc, &portsz) != 2)
512 return -EINVAL;
513
514 mutex_lock(&tracer.mutex);
515 if (cycacc)
516 tracer.flags |= TRACER_CYCLE_ACC;
517 else
518 tracer.flags &= ~TRACER_CYCLE_ACC;
519
520 tracer.etm_portsz = portsz & 0x0f;
521 mutex_unlock(&tracer.mutex);
522
523 return n;
524}
525
526static struct kobj_attribute trace_mode_attr =
527 __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
528
Ming Lei8e880692011-03-28 06:10:25 +0100529static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id)
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100530{
531 struct tracectx *t = &tracer;
532 int ret = 0;
533
534 if (t->etm_regs) {
535 dev_dbg(&dev->dev, "ETM already initialized\n");
536 ret = -EBUSY;
537 goto out;
538 }
539
540 ret = amba_request_regions(dev, NULL);
541 if (ret)
542 goto out;
543
544 t->etm_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
545 if (!t->etm_regs) {
546 ret = -ENOMEM;
547 goto out_release;
548 }
549
550 amba_set_drvdata(dev, t);
551
552 mutex_init(&t->mutex);
553 t->dev = &dev->dev;
554 t->flags = TRACER_CYCLE_ACC;
555 t->etm_portsz = 1;
556
557 etm_unlock(t);
Alexander Shishkin988257c2010-08-04 11:27:33 +0100558 (void)etm_readl(t, ETMMR_PDSR);
559 /* dummy first read */
560 (void)etm_readl(&tracer, ETMMR_OSSRR);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100561
562 t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf;
563 etm_writel(t, 0x440, ETMR_CTRL);
564 etm_lock(t);
565
566 ret = sysfs_create_file(&dev->dev.kobj,
567 &trace_running_attr.attr);
568 if (ret)
569 goto out_unmap;
570
571 /* failing to create any of these two is not fatal */
572 ret = sysfs_create_file(&dev->dev.kobj, &trace_info_attr.attr);
573 if (ret)
574 dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n");
575
576 ret = sysfs_create_file(&dev->dev.kobj, &trace_mode_attr.attr);
577 if (ret)
578 dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");
579
580 dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
581
582out:
583 return ret;
584
585out_unmap:
586 amba_set_drvdata(dev, NULL);
587 iounmap(t->etm_regs);
588
589out_release:
590 amba_release_regions(dev);
591
592 return ret;
593}
594
595static int etm_remove(struct amba_device *dev)
596{
597 struct tracectx *t = amba_get_drvdata(dev);
598
599 amba_set_drvdata(dev, NULL);
600
601 iounmap(t->etm_regs);
602 t->etm_regs = NULL;
603
604 amba_release_regions(dev);
605
606 sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr);
607 sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
608 sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr);
609
610 return 0;
611}
612
613static struct amba_id etm_ids[] = {
614 {
615 .id = 0x0003b921,
616 .mask = 0x0007ffff,
617 },
618 { 0, 0 },
619};
620
621static struct amba_driver etm_driver = {
622 .drv = {
623 .name = "etm",
624 .owner = THIS_MODULE,
625 },
626 .probe = etm_probe,
627 .remove = etm_remove,
628 .id_table = etm_ids,
629};
630
631static int __init etm_init(void)
632{
633 int retval;
634
635 retval = amba_driver_register(&etb_driver);
636 if (retval) {
637 printk(KERN_ERR "Failed to register etb\n");
638 return retval;
639 }
640
641 retval = amba_driver_register(&etm_driver);
642 if (retval) {
643 amba_driver_unregister(&etb_driver);
644 printk(KERN_ERR "Failed to probe etm\n");
645 return retval;
646 }
647
648 /* not being able to install this handler is not fatal */
649 (void)register_sysrq_key('v', &sysrq_etm_op);
650
651 return 0;
652}
653
654device_initcall(etm_init);
655