Linux Audio

Check our new training course

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