blob: b5f5aadf6f0ab61e4687ac2b42a92e8c6d51671e [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>
27#include <asm/hardware/coresight.h>
28#include <asm/sections.h>
29
30MODULE_LICENSE("GPL");
31MODULE_AUTHOR("Alexander Shishkin");
32
Alexander Shishkin8234eae2010-08-04 11:22:43 +010033/*
34 * ETM tracer state
35 */
36struct tracectx {
37 unsigned int etb_bufsz;
38 void __iomem *etb_regs;
39 void __iomem *etm_regs;
40 unsigned long flags;
41 int ncmppairs;
42 int etm_portsz;
Arve Hjønnevåg51495972011-01-28 23:44:43 -080043 unsigned long range_start;
44 unsigned long range_end;
Arve Hjønnevåg81e43122011-01-31 18:33:55 -080045 unsigned long data_range_start;
46 unsigned long data_range_end;
Alexander Shishkin8234eae2010-08-04 11:22:43 +010047 struct device *dev;
48 struct clk *emu_clk;
49 struct mutex mutex;
50};
51
Arve Hjønnevåg51495972011-01-28 23:44:43 -080052static struct tracectx tracer = {
53 .range_start = (unsigned long)_stext,
54 .range_end = (unsigned long)_etext,
55};
Alexander Shishkinc5d6c772009-12-01 14:00:51 +010056
57static inline bool trace_isrunning(struct tracectx *t)
58{
59 return !!(t->flags & TRACER_RUNNING);
60}
61
62static int etm_setup_address_range(struct tracectx *t, int n,
63 unsigned long start, unsigned long end, int exclude, int data)
64{
Arve Hjønnevågccd3dbc2011-01-28 23:33:11 -080065 u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_IGNSECURITY |
Alexander Shishkinc5d6c772009-12-01 14:00:51 +010066 ETMAAT_NOVALCMP;
67
68 if (n < 1 || n > t->ncmppairs)
69 return -EINVAL;
70
71 /* comparators and ranges are numbered starting with 1 as opposed
72 * to bits in a word */
73 n--;
74
75 if (data)
76 flags |= ETMAAT_DLOADSTORE;
77 else
78 flags |= ETMAAT_IEXEC;
79
80 /* first comparator for the range */
81 etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2));
82 etm_writel(t, start, ETMR_COMP_VAL(n * 2));
83
84 /* second comparator is right next to it */
85 etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
86 etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1));
87
Arve Hjønnevåg81e43122011-01-31 18:33:55 -080088 if (data) {
89 flags = exclude ? ETMVDC3_EXCLONLY : 0;
90 if (exclude)
91 n += 8;
92 etm_writel(t, flags | BIT(n), ETMR_VIEWDATACTRL3);
93 } else {
94 flags = exclude ? ETMTE_INCLEXCL : 0;
95 etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
96 }
Alexander Shishkinc5d6c772009-12-01 14:00:51 +010097
98 return 0;
99}
100
101static int trace_start(struct tracectx *t)
102{
103 u32 v;
104 unsigned long timeout = TRACER_TIMEOUT;
105
106 etb_unlock(t);
107
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800108 etb_writel(t, 0, ETBR_WRITEADDR);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100109 etb_writel(t, 0, ETBR_FORMATTERCTRL);
110 etb_writel(t, 1, ETBR_CTRL);
111
112 etb_lock(t);
113
114 /* configure etm */
115 v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz);
116
117 if (t->flags & TRACER_CYCLE_ACC)
118 v |= ETMCTRL_CYCLEACCURATE;
119
Arve Hjønnevåg81e43122011-01-31 18:33:55 -0800120 if (t->flags & TRACER_TRACE_DATA)
121 v |= ETMCTRL_DATA_DO_ADDR;
122
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100123 etm_unlock(t);
124
125 etm_writel(t, v, ETMR_CTRL);
126
127 while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
128 ;
129 if (!timeout) {
130 dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
131 etm_lock(t);
132 return -EFAULT;
133 }
134
Arve Hjønnevåg51495972011-01-28 23:44:43 -0800135 if (t->range_start || t->range_end)
136 etm_setup_address_range(t, 1,
137 t->range_start, t->range_end, 0, 0);
138 else
139 etm_writel(t, ETMTE_INCLEXCL, ETMR_TRACEENCTRL);
140
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100141 etm_writel(t, 0, ETMR_TRACEENCTRL2);
142 etm_writel(t, 0, ETMR_TRACESSCTRL);
143 etm_writel(t, 0x6f, ETMR_TRACEENEVT);
144
Arve Hjønnevåg81e43122011-01-31 18:33:55 -0800145 etm_writel(t, 0, ETMR_VIEWDATACTRL1);
146 etm_writel(t, 0, ETMR_VIEWDATACTRL2);
147
148 if (t->data_range_start || t->data_range_end)
149 etm_setup_address_range(t, 2, t->data_range_start,
150 t->data_range_end, 0, 1);
151 else
152 etm_writel(t, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3);
153
154 etm_writel(t, 0x6f, ETMR_VIEWDATAEVT);
155
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100156 v &= ~ETMCTRL_PROGRAM;
157 v |= ETMCTRL_PORTSEL;
158
159 etm_writel(t, v, ETMR_CTRL);
160
161 timeout = TRACER_TIMEOUT;
162 while (etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout)
163 ;
164 if (!timeout) {
165 dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n");
166 etm_lock(t);
167 return -EFAULT;
168 }
169
170 etm_lock(t);
171
172 t->flags |= TRACER_RUNNING;
173
174 return 0;
175}
176
177static int trace_stop(struct tracectx *t)
178{
179 unsigned long timeout = TRACER_TIMEOUT;
180
181 etm_unlock(t);
182
183 etm_writel(t, 0x440, ETMR_CTRL);
184 while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
185 ;
186 if (!timeout) {
187 dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
188 etm_lock(t);
189 return -EFAULT;
190 }
191
192 etm_lock(t);
193
194 etb_unlock(t);
195 etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL);
196
197 timeout = TRACER_TIMEOUT;
198 while (etb_readl(t, ETBR_FORMATTERCTRL) &
199 ETBFF_MANUAL_FLUSH && --timeout)
200 ;
201 if (!timeout) {
202 dev_dbg(t->dev, "Waiting for formatter flush to commence "
203 "timed out\n");
204 etb_lock(t);
205 return -EFAULT;
206 }
207
208 etb_writel(t, 0, ETBR_CTRL);
209
210 etb_lock(t);
211
212 t->flags &= ~TRACER_RUNNING;
213
214 return 0;
215}
216
217static int etb_getdatalen(struct tracectx *t)
218{
219 u32 v;
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800220 int wp;
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100221
222 v = etb_readl(t, ETBR_STATUS);
223
224 if (v & 1)
225 return t->etb_bufsz;
226
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100227 wp = etb_readl(t, ETBR_WRITEADDR);
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800228 return wp;
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100229}
230
231/* sysrq+v will always stop the running trace and leave it at that */
232static void etm_dump(void)
233{
234 struct tracectx *t = &tracer;
235 u32 first = 0;
236 int length;
237
238 if (!t->etb_regs) {
239 printk(KERN_INFO "No tracing hardware found\n");
240 return;
241 }
242
243 if (trace_isrunning(t))
244 trace_stop(t);
245
246 etb_unlock(t);
247
248 length = etb_getdatalen(t);
249
250 if (length == t->etb_bufsz)
251 first = etb_readl(t, ETBR_WRITEADDR);
252
253 etb_writel(t, first, ETBR_READADDR);
254
255 printk(KERN_INFO "Trace buffer contents length: %d\n", length);
256 printk(KERN_INFO "--- ETB buffer begin ---\n");
257 for (; length; length--)
258 printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM)));
259 printk(KERN_INFO "\n--- ETB buffer end ---\n");
260
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100261 etb_lock(t);
262}
263
Dmitry Torokhov1495cc92010-08-17 21:15:46 -0700264static void sysrq_etm_dump(int key)
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100265{
266 dev_dbg(tracer.dev, "Dumping ETB buffer\n");
267 etm_dump();
268}
269
270static struct sysrq_key_op sysrq_etm_op = {
271 .handler = sysrq_etm_dump,
272 .help_msg = "ETM buffer dump",
273 .action_msg = "etm",
274};
275
276static int etb_open(struct inode *inode, struct file *file)
277{
278 if (!tracer.etb_regs)
279 return -ENODEV;
280
281 file->private_data = &tracer;
282
283 return nonseekable_open(inode, file);
284}
285
286static ssize_t etb_read(struct file *file, char __user *data,
287 size_t len, loff_t *ppos)
288{
289 int total, i;
290 long length;
291 struct tracectx *t = file->private_data;
292 u32 first = 0;
293 u32 *buf;
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800294 int wpos;
295 int skip;
296 long wlength;
297 loff_t pos = *ppos;
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100298
299 mutex_lock(&t->mutex);
300
301 if (trace_isrunning(t)) {
302 length = 0;
303 goto out;
304 }
305
306 etb_unlock(t);
307
308 total = etb_getdatalen(t);
309 if (total == t->etb_bufsz)
310 first = etb_readl(t, ETBR_WRITEADDR);
311
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800312 if (pos > total * 4) {
313 skip = 0;
314 wpos = total;
315 } else {
316 skip = (int)pos % 4;
317 wpos = (int)pos / 4;
318 }
319 total -= wpos;
320 first = (first + wpos) % t->etb_bufsz;
321
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100322 etb_writel(t, first, ETBR_READADDR);
323
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800324 wlength = min(total, DIV_ROUND_UP(skip + (int)len, 4));
325 length = min(total * 4 - skip, (int)len);
326 buf = vmalloc(wlength * 4);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100327
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800328 dev_dbg(t->dev, "ETB read %ld bytes to %lld from %ld words at %d\n",
329 length, pos, wlength, first);
330 dev_dbg(t->dev, "ETB buffer length: %d\n", total + wpos);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100331 dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS));
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800332 for (i = 0; i < wlength; i++)
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100333 buf[i] = etb_readl(t, ETBR_READMEM);
334
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100335 etb_lock(t);
336
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800337 length -= copy_to_user(data, (u8 *)buf + skip, length);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100338 vfree(buf);
Arve Hjønnevåg5f388f32011-01-31 21:34:47 -0800339 *ppos = pos + length;
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100340
341out:
342 mutex_unlock(&t->mutex);
343
344 return length;
345}
346
347static int etb_release(struct inode *inode, struct file *file)
348{
349 /* there's nothing to do here, actually */
350 return 0;
351}
352
353static const struct file_operations etb_fops = {
354 .owner = THIS_MODULE,
355 .read = etb_read,
356 .open = etb_open,
357 .release = etb_release,
Arnd Bergmann6038f372010-08-15 18:52:59 +0200358 .llseek = no_llseek,
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100359};
360
361static struct miscdevice etb_miscdev = {
362 .name = "tracebuf",
363 .minor = 0,
364 .fops = &etb_fops,
365};
366
Ming Lei8e880692011-03-28 06:10:25 +0100367static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id)
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100368{
369 struct tracectx *t = &tracer;
370 int ret = 0;
371
372 ret = amba_request_regions(dev, NULL);
373 if (ret)
374 goto out;
375
376 t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
377 if (!t->etb_regs) {
378 ret = -ENOMEM;
379 goto out_release;
380 }
381
382 amba_set_drvdata(dev, t);
383
384 etb_miscdev.parent = &dev->dev;
385
386 ret = misc_register(&etb_miscdev);
387 if (ret)
388 goto out_unmap;
389
Arve Hjønnevåg875e2e12011-01-28 23:12:32 -0800390 /* Get optional clock. Currently used to select clock source on omap3 */
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100391 t->emu_clk = clk_get(&dev->dev, "emu_src_ck");
Arve Hjønnevåg875e2e12011-01-28 23:12:32 -0800392 if (IS_ERR(t->emu_clk))
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100393 dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n");
Arve Hjønnevåg875e2e12011-01-28 23:12:32 -0800394 else
395 clk_enable(t->emu_clk);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100396
397 etb_unlock(t);
398 t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
399 dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
400
401 /* make sure trace capture is disabled */
402 etb_writel(t, 0, ETBR_CTRL);
403 etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
404 etb_lock(t);
405
406 dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n");
407
408out:
409 return ret;
410
411out_unmap:
412 amba_set_drvdata(dev, NULL);
413 iounmap(t->etb_regs);
414
415out_release:
416 amba_release_regions(dev);
417
418 return ret;
419}
420
421static int etb_remove(struct amba_device *dev)
422{
423 struct tracectx *t = amba_get_drvdata(dev);
424
425 amba_set_drvdata(dev, NULL);
426
427 iounmap(t->etb_regs);
428 t->etb_regs = NULL;
429
Arve Hjønnevåg875e2e12011-01-28 23:12:32 -0800430 if (!IS_ERR(t->emu_clk)) {
431 clk_disable(t->emu_clk);
432 clk_put(t->emu_clk);
433 }
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100434
435 amba_release_regions(dev);
436
437 return 0;
438}
439
440static struct amba_id etb_ids[] = {
441 {
442 .id = 0x0003b907,
443 .mask = 0x0007ffff,
444 },
445 { 0, 0 },
446};
447
448static struct amba_driver etb_driver = {
449 .drv = {
450 .name = "etb",
451 .owner = THIS_MODULE,
452 },
453 .probe = etb_probe,
454 .remove = etb_remove,
455 .id_table = etb_ids,
456};
457
458/* use a sysfs file "trace_running" to start/stop tracing */
459static ssize_t trace_running_show(struct kobject *kobj,
460 struct kobj_attribute *attr,
461 char *buf)
462{
463 return sprintf(buf, "%x\n", trace_isrunning(&tracer));
464}
465
466static ssize_t trace_running_store(struct kobject *kobj,
467 struct kobj_attribute *attr,
468 const char *buf, size_t n)
469{
470 unsigned int value;
471 int ret;
472
473 if (sscanf(buf, "%u", &value) != 1)
474 return -EINVAL;
475
476 mutex_lock(&tracer.mutex);
477 ret = value ? trace_start(&tracer) : trace_stop(&tracer);
478 mutex_unlock(&tracer.mutex);
479
480 return ret ? : n;
481}
482
483static struct kobj_attribute trace_running_attr =
484 __ATTR(trace_running, 0644, trace_running_show, trace_running_store);
485
486static ssize_t trace_info_show(struct kobject *kobj,
487 struct kobj_attribute *attr,
488 char *buf)
489{
490 u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
491 int datalen;
492
493 etb_unlock(&tracer);
494 datalen = etb_getdatalen(&tracer);
495 etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
496 etb_ra = etb_readl(&tracer, ETBR_READADDR);
497 etb_st = etb_readl(&tracer, ETBR_STATUS);
498 etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
499 etb_lock(&tracer);
500
501 etm_unlock(&tracer);
502 etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
503 etm_st = etm_readl(&tracer, ETMR_STATUS);
504 etm_lock(&tracer);
505
506 return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
507 "ETBR_WRITEADDR:\t%08x\n"
508 "ETBR_READADDR:\t%08x\n"
509 "ETBR_STATUS:\t%08x\n"
510 "ETBR_FORMATTERCTRL:\t%08x\n"
511 "ETMR_CTRL:\t%08x\n"
512 "ETMR_STATUS:\t%08x\n",
513 datalen,
514 tracer.ncmppairs,
515 etb_wa,
516 etb_ra,
517 etb_st,
518 etb_fc,
519 etm_ctrl,
520 etm_st
521 );
522}
523
524static struct kobj_attribute trace_info_attr =
525 __ATTR(trace_info, 0444, trace_info_show, NULL);
526
527static ssize_t trace_mode_show(struct kobject *kobj,
528 struct kobj_attribute *attr,
529 char *buf)
530{
531 return sprintf(buf, "%d %d\n",
532 !!(tracer.flags & TRACER_CYCLE_ACC),
533 tracer.etm_portsz);
534}
535
536static ssize_t trace_mode_store(struct kobject *kobj,
537 struct kobj_attribute *attr,
538 const char *buf, size_t n)
539{
540 unsigned int cycacc, portsz;
541
542 if (sscanf(buf, "%u %u", &cycacc, &portsz) != 2)
543 return -EINVAL;
544
545 mutex_lock(&tracer.mutex);
546 if (cycacc)
547 tracer.flags |= TRACER_CYCLE_ACC;
548 else
549 tracer.flags &= ~TRACER_CYCLE_ACC;
550
551 tracer.etm_portsz = portsz & 0x0f;
552 mutex_unlock(&tracer.mutex);
553
554 return n;
555}
556
557static struct kobj_attribute trace_mode_attr =
558 __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
559
Arve Hjønnevåg51495972011-01-28 23:44:43 -0800560static ssize_t trace_range_show(struct kobject *kobj,
561 struct kobj_attribute *attr,
562 char *buf)
563{
564 return sprintf(buf, "%08lx %08lx\n",
565 tracer.range_start, tracer.range_end);
566}
567
568static ssize_t trace_range_store(struct kobject *kobj,
569 struct kobj_attribute *attr,
570 const char *buf, size_t n)
571{
572 unsigned long range_start, range_end;
573
574 if (sscanf(buf, "%lx %lx", &range_start, &range_end) != 2)
575 return -EINVAL;
576
577 mutex_lock(&tracer.mutex);
578 tracer.range_start = range_start;
579 tracer.range_end = range_end;
580 mutex_unlock(&tracer.mutex);
581
582 return n;
583}
584
585
586static struct kobj_attribute trace_range_attr =
587 __ATTR(trace_range, 0644, trace_range_show, trace_range_store);
588
Arve Hjønnevåg81e43122011-01-31 18:33:55 -0800589static ssize_t trace_data_range_show(struct kobject *kobj,
590 struct kobj_attribute *attr,
591 char *buf)
592{
593 unsigned long range_start;
594 u64 range_end;
595 mutex_lock(&tracer.mutex);
596 range_start = tracer.data_range_start;
597 range_end = tracer.data_range_end;
598 if (!range_end && (tracer.flags & TRACER_TRACE_DATA))
599 range_end = 0x100000000ULL;
600 mutex_unlock(&tracer.mutex);
601 return sprintf(buf, "%08lx %08llx\n", range_start, range_end);
602}
603
604static ssize_t trace_data_range_store(struct kobject *kobj,
605 struct kobj_attribute *attr,
606 const char *buf, size_t n)
607{
608 unsigned long range_start;
609 u64 range_end;
610
611 if (sscanf(buf, "%lx %llx", &range_start, &range_end) != 2)
612 return -EINVAL;
613
614 mutex_lock(&tracer.mutex);
615 tracer.data_range_start = range_start;
616 tracer.data_range_end = (unsigned long)range_end;
617 if (range_end)
618 tracer.flags |= TRACER_TRACE_DATA;
619 else
620 tracer.flags &= ~TRACER_TRACE_DATA;
621 mutex_unlock(&tracer.mutex);
622
623 return n;
624}
625
626
627static struct kobj_attribute trace_data_range_attr =
628 __ATTR(trace_data_range, 0644,
629 trace_data_range_show, trace_data_range_store);
630
Ming Lei8e880692011-03-28 06:10:25 +0100631static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id)
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100632{
633 struct tracectx *t = &tracer;
634 int ret = 0;
635
636 if (t->etm_regs) {
637 dev_dbg(&dev->dev, "ETM already initialized\n");
638 ret = -EBUSY;
639 goto out;
640 }
641
642 ret = amba_request_regions(dev, NULL);
643 if (ret)
644 goto out;
645
646 t->etm_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
647 if (!t->etm_regs) {
648 ret = -ENOMEM;
649 goto out_release;
650 }
651
652 amba_set_drvdata(dev, t);
653
654 mutex_init(&t->mutex);
655 t->dev = &dev->dev;
Arve Hjønnevåg81e43122011-01-31 18:33:55 -0800656 t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100657 t->etm_portsz = 1;
658
659 etm_unlock(t);
Alexander Shishkin988257c2010-08-04 11:27:33 +0100660 (void)etm_readl(t, ETMMR_PDSR);
661 /* dummy first read */
662 (void)etm_readl(&tracer, ETMMR_OSSRR);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100663
664 t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf;
665 etm_writel(t, 0x440, ETMR_CTRL);
666 etm_lock(t);
667
668 ret = sysfs_create_file(&dev->dev.kobj,
669 &trace_running_attr.attr);
670 if (ret)
671 goto out_unmap;
672
673 /* failing to create any of these two is not fatal */
674 ret = sysfs_create_file(&dev->dev.kobj, &trace_info_attr.attr);
675 if (ret)
676 dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n");
677
678 ret = sysfs_create_file(&dev->dev.kobj, &trace_mode_attr.attr);
679 if (ret)
680 dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");
681
Arve Hjønnevåg51495972011-01-28 23:44:43 -0800682 ret = sysfs_create_file(&dev->dev.kobj, &trace_range_attr.attr);
683 if (ret)
684 dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");
685
Arve Hjønnevåg81e43122011-01-31 18:33:55 -0800686 ret = sysfs_create_file(&dev->dev.kobj, &trace_data_range_attr.attr);
687 if (ret)
688 dev_dbg(&dev->dev,
689 "Failed to create trace_data_range in sysfs\n");
690
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100691 dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
692
693out:
694 return ret;
695
696out_unmap:
697 amba_set_drvdata(dev, NULL);
698 iounmap(t->etm_regs);
699
700out_release:
701 amba_release_regions(dev);
702
703 return ret;
704}
705
706static int etm_remove(struct amba_device *dev)
707{
708 struct tracectx *t = amba_get_drvdata(dev);
709
710 amba_set_drvdata(dev, NULL);
711
712 iounmap(t->etm_regs);
713 t->etm_regs = NULL;
714
715 amba_release_regions(dev);
716
717 sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr);
718 sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
719 sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr);
Arve Hjønnevåg51495972011-01-28 23:44:43 -0800720 sysfs_remove_file(&dev->dev.kobj, &trace_range_attr.attr);
Arve Hjønnevåg81e43122011-01-31 18:33:55 -0800721 sysfs_remove_file(&dev->dev.kobj, &trace_data_range_attr.attr);
Alexander Shishkinc5d6c772009-12-01 14:00:51 +0100722
723 return 0;
724}
725
726static struct amba_id etm_ids[] = {
727 {
728 .id = 0x0003b921,
729 .mask = 0x0007ffff,
730 },
731 { 0, 0 },
732};
733
734static struct amba_driver etm_driver = {
735 .drv = {
736 .name = "etm",
737 .owner = THIS_MODULE,
738 },
739 .probe = etm_probe,
740 .remove = etm_remove,
741 .id_table = etm_ids,
742};
743
744static int __init etm_init(void)
745{
746 int retval;
747
748 retval = amba_driver_register(&etb_driver);
749 if (retval) {
750 printk(KERN_ERR "Failed to register etb\n");
751 return retval;
752 }
753
754 retval = amba_driver_register(&etm_driver);
755 if (retval) {
756 amba_driver_unregister(&etb_driver);
757 printk(KERN_ERR "Failed to probe etm\n");
758 return retval;
759 }
760
761 /* not being able to install this handler is not fatal */
762 (void)register_sysrq_key('v', &sysrq_etm_op);
763
764 return 0;
765}
766
767device_initcall(etm_init);
768