diff options
author | Kevin Hilman <khilman@linaro.org> | 2015-05-22 14:09:27 -0700 |
---|---|---|
committer | Kevin Hilman <khilman@linaro.org> | 2015-05-22 14:09:27 -0700 |
commit | 5360f41d9a5160bf850fce3cac62d56443c58b3f (patch) | |
tree | c603057f0ad05dfcd5bb7746607f90aa4be29fb7 | |
parent | 8b888de4a1ceae8a86f645c208651dfb08e4dd05 (diff) | |
parent | a61d3b775855a1d67d97ca0aa389489cb8a9320d (diff) |
Merge branch 'linux-linaro-lsk-v3.18' into linux-linaro-lsk-v3.18-rt
-rw-r--r-- | arch/arm/Kconfig.debug | 8 | ||||
-rw-r--r-- | arch/arm/include/asm/hardware/coresight.h | 157 | ||||
-rw-r--r-- | arch/arm/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/kernel/etm.c | 654 | ||||
-rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/Kconfig | 22 | ||||
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/emu.c | 50 | ||||
-rw-r--r-- | linaro/configs/android.conf | 42 | ||||
-rw-r--r-- | linaro/configs/preempt-rt.conf | 1 |
10 files changed, 880 insertions, 60 deletions
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 5c2b8eab990e..21c031fe76d8 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -1297,6 +1297,14 @@ config EARLY_PRINTK kernel low-level debugging functions. Add earlyprintk to your kernel parameters to enable this console. +config OC_ETM + bool "On-chip ETM and ETB" + depends on ARM_AMBA && !CORESIGHT + help + Enables the on-chip embedded trace macrocell and embedded trace + buffer driver that will allow you to collect traces of the + kernel code. + config ARM_KPROBES_TEST tristate "Kprobes test module" depends on KPROBES && MODULES diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h new file mode 100644 index 000000000000..ad774f37c47c --- /dev/null +++ b/arch/arm/include/asm/hardware/coresight.h @@ -0,0 +1,157 @@ +/* + * linux/arch/arm/include/asm/hardware/coresight.h + * + * CoreSight components' registers + * + * Copyright (C) 2009 Nokia Corporation. + * Alexander Shishkin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_HARDWARE_CORESIGHT_H +#define __ASM_HARDWARE_CORESIGHT_H + +#define TRACER_ACCESSED_BIT 0 +#define TRACER_RUNNING_BIT 1 +#define TRACER_CYCLE_ACC_BIT 2 +#define TRACER_ACCESSED BIT(TRACER_ACCESSED_BIT) +#define TRACER_RUNNING BIT(TRACER_RUNNING_BIT) +#define TRACER_CYCLE_ACC BIT(TRACER_CYCLE_ACC_BIT) + +#define TRACER_TIMEOUT 10000 + +#define etm_writel(t, v, x) \ + (writel_relaxed((v), (t)->etm_regs + (x))) +#define etm_readl(t, x) (readl_relaxed((t)->etm_regs + (x))) + +/* CoreSight Management Registers */ +#define CSMR_LOCKACCESS 0xfb0 +#define CSMR_LOCKSTATUS 0xfb4 +#define CSMR_AUTHSTATUS 0xfb8 +#define CSMR_DEVID 0xfc8 +#define CSMR_DEVTYPE 0xfcc +/* CoreSight Component Registers */ +#define CSCR_CLASS 0xff4 + +#define CS_LAR_KEY 0xc5acce55 + +/* ETM control register, "ETM Architecture", 3.3.1 */ +#define ETMR_CTRL 0 +#define ETMCTRL_POWERDOWN 1 +#define ETMCTRL_PROGRAM (1 << 10) +#define ETMCTRL_PORTSEL (1 << 11) +#define ETMCTRL_DO_CONTEXTID (3 << 14) +#define ETMCTRL_PORTMASK1 (7 << 4) +#define ETMCTRL_PORTMASK2 (1 << 21) +#define ETMCTRL_PORTMASK (ETMCTRL_PORTMASK1 | ETMCTRL_PORTMASK2) +#define ETMCTRL_PORTSIZE(x) ((((x) & 7) << 4) | (!!((x) & 8)) << 21) +#define ETMCTRL_DO_CPRT (1 << 1) +#define ETMCTRL_DATAMASK (3 << 2) +#define ETMCTRL_DATA_DO_DATA (1 << 2) +#define ETMCTRL_DATA_DO_ADDR (1 << 3) +#define ETMCTRL_DATA_DO_BOTH (ETMCTRL_DATA_DO_DATA | ETMCTRL_DATA_DO_ADDR) +#define ETMCTRL_BRANCH_OUTPUT (1 << 8) +#define ETMCTRL_CYCLEACCURATE (1 << 12) + +/* ETM configuration code register */ +#define ETMR_CONFCODE (0x04) + +/* ETM trace start/stop resource control register */ +#define ETMR_TRACESSCTRL (0x18) + +/* ETM trigger event register */ +#define ETMR_TRIGEVT (0x08) + +/* address access type register bits, "ETM architecture", + * table 3-27 */ +/* - access type */ +#define ETMAAT_IFETCH 0 +#define ETMAAT_IEXEC 1 +#define ETMAAT_IEXECPASS 2 +#define ETMAAT_IEXECFAIL 3 +#define ETMAAT_DLOADSTORE 4 +#define ETMAAT_DLOAD 5 +#define ETMAAT_DSTORE 6 +/* - comparison access size */ +#define ETMAAT_JAVA (0 << 3) +#define ETMAAT_THUMB (1 << 3) +#define ETMAAT_ARM (3 << 3) +/* - data value comparison control */ +#define ETMAAT_NOVALCMP (0 << 5) +#define ETMAAT_VALMATCH (1 << 5) +#define ETMAAT_VALNOMATCH (3 << 5) +/* - exact match */ +#define ETMAAT_EXACTMATCH (1 << 7) +/* - context id comparator control */ +#define ETMAAT_IGNCONTEXTID (0 << 8) +#define ETMAAT_VALUE1 (1 << 8) +#define ETMAAT_VALUE2 (2 << 8) +#define ETMAAT_VALUE3 (3 << 8) +/* - security level control */ +#define ETMAAT_IGNSECURITY (0 << 10) +#define ETMAAT_NSONLY (1 << 10) +#define ETMAAT_SONLY (2 << 10) + +#define ETMR_COMP_VAL(x) (0x40 + (x) * 4) +#define ETMR_COMP_ACC_TYPE(x) (0x80 + (x) * 4) + +/* ETM status register, "ETM Architecture", 3.3.2 */ +#define ETMR_STATUS (0x10) +#define ETMST_OVERFLOW BIT(0) +#define ETMST_PROGBIT BIT(1) +#define ETMST_STARTSTOP BIT(2) +#define ETMST_TRIGGER BIT(3) + +#define etm_progbit(t) (etm_readl((t), ETMR_STATUS) & ETMST_PROGBIT) +#define etm_started(t) (etm_readl((t), ETMR_STATUS) & ETMST_STARTSTOP) +#define etm_triggered(t) (etm_readl((t), ETMR_STATUS) & ETMST_TRIGGER) + +#define ETMR_TRACEENCTRL2 0x1c +#define ETMR_TRACEENCTRL 0x24 +#define ETMTE_INCLEXCL BIT(24) +#define ETMR_TRACEENEVT 0x20 +#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \ + ETMCTRL_DATA_DO_ADDR | \ + ETMCTRL_BRANCH_OUTPUT | \ + ETMCTRL_DO_CONTEXTID) + +/* ETM management registers, "ETM Architecture", 3.5.24 */ +#define ETMMR_OSLAR 0x300 +#define ETMMR_OSLSR 0x304 +#define ETMMR_OSSRR 0x308 +#define ETMMR_PDSR 0x314 + +/* ETB registers, "CoreSight Components TRM", 9.3 */ +#define ETBR_DEPTH 0x04 +#define ETBR_STATUS 0x0c +#define ETBR_READMEM 0x10 +#define ETBR_READADDR 0x14 +#define ETBR_WRITEADDR 0x18 +#define ETBR_TRIGGERCOUNT 0x1c +#define ETBR_CTRL 0x20 +#define ETBR_FORMATTERCTRL 0x304 +#define ETBFF_ENFTC 1 +#define ETBFF_ENFCONT BIT(1) +#define ETBFF_FONFLIN BIT(4) +#define ETBFF_MANUAL_FLUSH BIT(6) +#define ETBFF_TRIGIN BIT(8) +#define ETBFF_TRIGEVT BIT(9) +#define ETBFF_TRIGFL BIT(10) + +#define etb_writel(t, v, x) \ + (writel_relaxed((v), (t)->etb_regs + (x))) +#define etb_readl(t, x) (readl_relaxed((t)->etb_regs + (x))) + +#define etm_lock(t) do { etm_writel((t), 0, CSMR_LOCKACCESS); } while (0) +#define etm_unlock(t) \ + do { etm_writel((t), CS_LAR_KEY, CSMR_LOCKACCESS); } while (0) + +#define etb_lock(t) do { etb_writel((t), 0, CSMR_LOCKACCESS); } while (0) +#define etb_unlock(t) \ + do { etb_writel((t), CS_LAR_KEY, CSMR_LOCKACCESS); } while (0) + +#endif /* __ASM_HARDWARE_CORESIGHT_H */ + diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index db74bb5b88b0..03120e656aea 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -30,6 +30,7 @@ else obj-y += entry-armv.o endif +obj-$(CONFIG_OC_ETM) += etm.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_ISA_DMA_API) += dma.o obj-$(CONFIG_FIQ) += fiq.o fiqasm.o diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c new file mode 100644 index 000000000000..131a6ab5f355 --- /dev/null +++ b/arch/arm/kernel/etm.c @@ -0,0 +1,654 @@ +/* + * linux/arch/arm/kernel/etm.c + * + * Driver for ARM's Embedded Trace Macrocell and Embedded Trace Buffer. + * + * Copyright (C) 2009 Nokia Corporation. + * Alexander Shishkin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/io.h> +#include <linux/sysrq.h> +#include <linux/device.h> +#include <linux/clk.h> +#include <linux/amba/bus.h> +#include <linux/fs.h> +#include <linux/uaccess.h> +#include <linux/miscdevice.h> +#include <linux/vmalloc.h> +#include <linux/mutex.h> +#include <linux/module.h> +#include <asm/hardware/coresight.h> +#include <asm/sections.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexander Shishkin"); + +/* + * ETM tracer state + */ +struct tracectx { + unsigned int etb_bufsz; + void __iomem *etb_regs; + void __iomem *etm_regs; + unsigned long flags; + int ncmppairs; + int etm_portsz; + struct device *dev; + struct clk *emu_clk; + struct mutex mutex; +}; + +static struct tracectx tracer; + +static inline bool trace_isrunning(struct tracectx *t) +{ + return !!(t->flags & TRACER_RUNNING); +} + +static int etm_setup_address_range(struct tracectx *t, int n, + unsigned long start, unsigned long end, int exclude, int data) +{ + u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \ + ETMAAT_NOVALCMP; + + if (n < 1 || n > t->ncmppairs) + return -EINVAL; + + /* comparators and ranges are numbered starting with 1 as opposed + * to bits in a word */ + n--; + + if (data) + flags |= ETMAAT_DLOADSTORE; + else + flags |= ETMAAT_IEXEC; + + /* first comparator for the range */ + etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2)); + etm_writel(t, start, ETMR_COMP_VAL(n * 2)); + + /* second comparator is right next to it */ + etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1)); + etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1)); + + flags = exclude ? ETMTE_INCLEXCL : 0; + etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL); + + return 0; +} + +static int trace_start(struct tracectx *t) +{ + u32 v; + unsigned long timeout = TRACER_TIMEOUT; + + etb_unlock(t); + + etb_writel(t, 0, ETBR_FORMATTERCTRL); + etb_writel(t, 1, ETBR_CTRL); + + etb_lock(t); + + /* configure etm */ + v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz); + + if (t->flags & TRACER_CYCLE_ACC) + v |= ETMCTRL_CYCLEACCURATE; + + etm_unlock(t); + + etm_writel(t, v, ETMR_CTRL); + + while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) + ; + if (!timeout) { + dev_dbg(t->dev, "Waiting for progbit to assert timed out\n"); + etm_lock(t); + return -EFAULT; + } + + etm_setup_address_range(t, 1, (unsigned long)_stext, + (unsigned long)_etext, 0, 0); + etm_writel(t, 0, ETMR_TRACEENCTRL2); + etm_writel(t, 0, ETMR_TRACESSCTRL); + etm_writel(t, 0x6f, ETMR_TRACEENEVT); + + v &= ~ETMCTRL_PROGRAM; + v |= ETMCTRL_PORTSEL; + + etm_writel(t, v, ETMR_CTRL); + + timeout = TRACER_TIMEOUT; + while (etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout) + ; + if (!timeout) { + dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n"); + etm_lock(t); + return -EFAULT; + } + + etm_lock(t); + + t->flags |= TRACER_RUNNING; + + return 0; +} + +static int trace_stop(struct tracectx *t) +{ + unsigned long timeout = TRACER_TIMEOUT; + + etm_unlock(t); + + etm_writel(t, 0x440, ETMR_CTRL); + while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) + ; + if (!timeout) { + dev_dbg(t->dev, "Waiting for progbit to assert timed out\n"); + etm_lock(t); + return -EFAULT; + } + + etm_lock(t); + + etb_unlock(t); + etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL); + + timeout = TRACER_TIMEOUT; + while (etb_readl(t, ETBR_FORMATTERCTRL) & + ETBFF_MANUAL_FLUSH && --timeout) + ; + if (!timeout) { + dev_dbg(t->dev, "Waiting for formatter flush to commence " + "timed out\n"); + etb_lock(t); + return -EFAULT; + } + + etb_writel(t, 0, ETBR_CTRL); + + etb_lock(t); + + t->flags &= ~TRACER_RUNNING; + + return 0; +} + +static int etb_getdatalen(struct tracectx *t) +{ + u32 v; + int rp, wp; + + v = etb_readl(t, ETBR_STATUS); + + if (v & 1) + return t->etb_bufsz; + + rp = etb_readl(t, ETBR_READADDR); + wp = etb_readl(t, ETBR_WRITEADDR); + + if (rp > wp) { + etb_writel(t, 0, ETBR_READADDR); + etb_writel(t, 0, ETBR_WRITEADDR); + + return 0; + } + + return wp - rp; +} + +/* sysrq+v will always stop the running trace and leave it at that */ +static void etm_dump(void) +{ + struct tracectx *t = &tracer; + u32 first = 0; + int length; + + if (!t->etb_regs) { + printk(KERN_INFO "No tracing hardware found\n"); + return; + } + + if (trace_isrunning(t)) + trace_stop(t); + + etb_unlock(t); + + length = etb_getdatalen(t); + + if (length == t->etb_bufsz) + first = etb_readl(t, ETBR_WRITEADDR); + + etb_writel(t, first, ETBR_READADDR); + + printk(KERN_INFO "Trace buffer contents length: %d\n", length); + printk(KERN_INFO "--- ETB buffer begin ---\n"); + for (; length; length--) + printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM))); + printk(KERN_INFO "\n--- ETB buffer end ---\n"); + + /* deassert the overflow bit */ + etb_writel(t, 1, ETBR_CTRL); + etb_writel(t, 0, ETBR_CTRL); + + etb_writel(t, 0, ETBR_TRIGGERCOUNT); + etb_writel(t, 0, ETBR_READADDR); + etb_writel(t, 0, ETBR_WRITEADDR); + + etb_lock(t); +} + +static void sysrq_etm_dump(int key) +{ + dev_dbg(tracer.dev, "Dumping ETB buffer\n"); + etm_dump(); +} + +static struct sysrq_key_op sysrq_etm_op = { + .handler = sysrq_etm_dump, + .help_msg = "etm-buffer-dump(v)", + .action_msg = "etm", +}; + +static int etb_open(struct inode *inode, struct file *file) +{ + if (!tracer.etb_regs) + return -ENODEV; + + file->private_data = &tracer; + + return nonseekable_open(inode, file); +} + +static ssize_t etb_read(struct file *file, char __user *data, + size_t len, loff_t *ppos) +{ + int total, i; + long length; + struct tracectx *t = file->private_data; + u32 first = 0; + u32 *buf; + + mutex_lock(&t->mutex); + + if (trace_isrunning(t)) { + length = 0; + goto out; + } + + etb_unlock(t); + + total = etb_getdatalen(t); + if (total == t->etb_bufsz) + first = etb_readl(t, ETBR_WRITEADDR); + + etb_writel(t, first, ETBR_READADDR); + + length = min(total * 4, (int)len); + buf = vmalloc(length); + + dev_dbg(t->dev, "ETB buffer length: %d\n", total); + dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS)); + for (i = 0; i < length / 4; i++) + buf[i] = etb_readl(t, ETBR_READMEM); + + /* the only way to deassert overflow bit in ETB status is this */ + etb_writel(t, 1, ETBR_CTRL); + etb_writel(t, 0, ETBR_CTRL); + + etb_writel(t, 0, ETBR_WRITEADDR); + etb_writel(t, 0, ETBR_READADDR); + etb_writel(t, 0, ETBR_TRIGGERCOUNT); + + etb_lock(t); + + length -= copy_to_user(data, buf, length); + vfree(buf); + +out: + mutex_unlock(&t->mutex); + + return length; +} + +static int etb_release(struct inode *inode, struct file *file) +{ + /* there's nothing to do here, actually */ + return 0; +} + +static const struct file_operations etb_fops = { + .owner = THIS_MODULE, + .read = etb_read, + .open = etb_open, + .release = etb_release, + .llseek = no_llseek, +}; + +static struct miscdevice etb_miscdev = { + .name = "tracebuf", + .minor = 0, + .fops = &etb_fops, +}; + +static int etb_probe(struct amba_device *dev, const struct amba_id *id) +{ + struct tracectx *t = &tracer; + int ret = 0; + + ret = amba_request_regions(dev, NULL); + if (ret) + goto out; + + t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res)); + if (!t->etb_regs) { + ret = -ENOMEM; + goto out_release; + } + + amba_set_drvdata(dev, t); + + etb_miscdev.parent = &dev->dev; + + ret = misc_register(&etb_miscdev); + if (ret) + goto out_unmap; + + t->emu_clk = clk_get(&dev->dev, "emu_src_ck"); + if (IS_ERR(t->emu_clk)) { + dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n"); + return -EFAULT; + } + + clk_enable(t->emu_clk); + + etb_unlock(t); + t->etb_bufsz = etb_readl(t, ETBR_DEPTH); + dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz); + + /* make sure trace capture is disabled */ + etb_writel(t, 0, ETBR_CTRL); + etb_writel(t, 0x1000, ETBR_FORMATTERCTRL); + etb_lock(t); + + dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n"); + +out: + return ret; + +out_unmap: + iounmap(t->etb_regs); + +out_release: + amba_release_regions(dev); + + return ret; +} + +static int etb_remove(struct amba_device *dev) +{ + struct tracectx *t = amba_get_drvdata(dev); + + iounmap(t->etb_regs); + t->etb_regs = NULL; + + clk_disable(t->emu_clk); + clk_put(t->emu_clk); + + amba_release_regions(dev); + + return 0; +} + +static struct amba_id etb_ids[] = { + { + .id = 0x0003b907, + .mask = 0x0007ffff, + }, + { 0, 0 }, +}; + +static struct amba_driver etb_driver = { + .drv = { + .name = "etb", + .owner = THIS_MODULE, + }, + .probe = etb_probe, + .remove = etb_remove, + .id_table = etb_ids, +}; + +/* use a sysfs file "trace_running" to start/stop tracing */ +static ssize_t trace_running_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%x\n", trace_isrunning(&tracer)); +} + +static ssize_t trace_running_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t n) +{ + unsigned int value; + int ret; + + if (sscanf(buf, "%u", &value) != 1) + return -EINVAL; + + mutex_lock(&tracer.mutex); + ret = value ? trace_start(&tracer) : trace_stop(&tracer); + mutex_unlock(&tracer.mutex); + + return ret ? : n; +} + +static struct kobj_attribute trace_running_attr = + __ATTR(trace_running, 0644, trace_running_show, trace_running_store); + +static ssize_t trace_info_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st; + int datalen; + + etb_unlock(&tracer); + datalen = etb_getdatalen(&tracer); + etb_wa = etb_readl(&tracer, ETBR_WRITEADDR); + etb_ra = etb_readl(&tracer, ETBR_READADDR); + etb_st = etb_readl(&tracer, ETBR_STATUS); + etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL); + etb_lock(&tracer); + + etm_unlock(&tracer); + etm_ctrl = etm_readl(&tracer, ETMR_CTRL); + etm_st = etm_readl(&tracer, ETMR_STATUS); + etm_lock(&tracer); + + return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n" + "ETBR_WRITEADDR:\t%08x\n" + "ETBR_READADDR:\t%08x\n" + "ETBR_STATUS:\t%08x\n" + "ETBR_FORMATTERCTRL:\t%08x\n" + "ETMR_CTRL:\t%08x\n" + "ETMR_STATUS:\t%08x\n", + datalen, + tracer.ncmppairs, + etb_wa, + etb_ra, + etb_st, + etb_fc, + etm_ctrl, + etm_st + ); +} + +static struct kobj_attribute trace_info_attr = + __ATTR(trace_info, 0444, trace_info_show, NULL); + +static ssize_t trace_mode_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d %d\n", + !!(tracer.flags & TRACER_CYCLE_ACC), + tracer.etm_portsz); +} + +static ssize_t trace_mode_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t n) +{ + unsigned int cycacc, portsz; + + if (sscanf(buf, "%u %u", &cycacc, &portsz) != 2) + return -EINVAL; + + mutex_lock(&tracer.mutex); + if (cycacc) + tracer.flags |= TRACER_CYCLE_ACC; + else + tracer.flags &= ~TRACER_CYCLE_ACC; + + tracer.etm_portsz = portsz & 0x0f; + mutex_unlock(&tracer.mutex); + + return n; +} + +static struct kobj_attribute trace_mode_attr = + __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store); + +static int etm_probe(struct amba_device *dev, const struct amba_id *id) +{ + struct tracectx *t = &tracer; + int ret = 0; + + if (t->etm_regs) { + dev_dbg(&dev->dev, "ETM already initialized\n"); + ret = -EBUSY; + goto out; + } + + ret = amba_request_regions(dev, NULL); + if (ret) + goto out; + + t->etm_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res)); + if (!t->etm_regs) { + ret = -ENOMEM; + goto out_release; + } + + amba_set_drvdata(dev, t); + + mutex_init(&t->mutex); + t->dev = &dev->dev; + t->flags = TRACER_CYCLE_ACC; + t->etm_portsz = 1; + + etm_unlock(t); + (void)etm_readl(t, ETMMR_PDSR); + /* dummy first read */ + (void)etm_readl(&tracer, ETMMR_OSSRR); + + t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf; + etm_writel(t, 0x440, ETMR_CTRL); + etm_lock(t); + + ret = sysfs_create_file(&dev->dev.kobj, + &trace_running_attr.attr); + if (ret) + goto out_unmap; + + /* failing to create any of these two is not fatal */ + ret = sysfs_create_file(&dev->dev.kobj, &trace_info_attr.attr); + if (ret) + dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n"); + + ret = sysfs_create_file(&dev->dev.kobj, &trace_mode_attr.attr); + if (ret) + dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n"); + + dev_dbg(t->dev, "ETM AMBA driver initialized.\n"); + +out: + return ret; + +out_unmap: + iounmap(t->etm_regs); + +out_release: + amba_release_regions(dev); + + return ret; +} + +static int etm_remove(struct amba_device *dev) +{ + struct tracectx *t = amba_get_drvdata(dev); + + iounmap(t->etm_regs); + t->etm_regs = NULL; + + amba_release_regions(dev); + + sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr); + sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr); + sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr); + + return 0; +} + +static struct amba_id etm_ids[] = { + { + .id = 0x0003b921, + .mask = 0x0007ffff, + }, + { 0, 0 }, +}; + +static struct amba_driver etm_driver = { + .drv = { + .name = "etm", + .owner = THIS_MODULE, + }, + .probe = etm_probe, + .remove = etm_remove, + .id_table = etm_ids, +}; + +static int __init etm_init(void) +{ + int retval; + + retval = amba_driver_register(&etb_driver); + if (retval) { + printk(KERN_ERR "Failed to register etb\n"); + return retval; + } + + retval = amba_driver_register(&etm_driver); + if (retval) { + amba_driver_unregister(&etb_driver); + printk(KERN_ERR "Failed to probe etm\n"); + return retval; + } + + /* not being able to install this handler is not fatal */ + (void)register_sysrq_key('v', &sysrq_etm_op); + + return 0; +} + +device_initcall(etm_init); + diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 7fc70ae21185..b5b452f90f76 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -29,7 +29,6 @@ #include <linux/hw_breakpoint.h> #include <linux/smp.h> #include <linux/cpu_pm.h> -#include <linux/coresight.h> #include <asm/cacheflush.h> #include <asm/cputype.h> @@ -37,6 +36,7 @@ #include <asm/hw_breakpoint.h> #include <asm/kdebug.h> #include <asm/traps.h> +#include <asm/hardware/coresight.h> /* Breakpoint currently in use for each BRP. */ static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); @@ -976,7 +976,7 @@ static void reset_ctrl_regs(void *unused) * Unconditionally clear the OS lock by writing a value * other than CS_LAR_KEY to the access register. */ - ARM_DBG_WRITE(c1, c0, 4, ~CORESIGHT_UNLOCK); + ARM_DBG_WRITE(c1, c0, 4, ~CS_LAR_KEY); isb(); /* diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 4a63d3311a41..f4d06aea8460 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -292,21 +292,13 @@ config MACH_TI8148EVM depends on SOC_TI81XX default y -config MACH_OMAP_4430SDP - bool "OMAP 4430 SDP board" - default y - depends on ARCH_OMAP4 - select OMAP_PACKAGE_CBL - select OMAP_PACKAGE_CBS - select REGULATOR_FIXED_VOLTAGE if REGULATOR - -config MACH_OMAP4_PANDA - bool "OMAP4 Panda Board" - default y - depends on ARCH_OMAP4 - select OMAP_PACKAGE_CBL - select OMAP_PACKAGE_CBS - select REGULATOR_FIXED_VOLTAGE if REGULATOR +config OMAP3_EMU + bool "OMAP3 debugging peripherals" + depends on ARCH_OMAP3 + select ARM_AMBA + select OC_ETM + help + Say Y here to enable debugging hardware of omap3 config OMAP3_SDRC_AC_TIMING bool "Enable SDRC AC timing register changes" diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 87255a3d8849..d9e94122073e 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -228,6 +228,7 @@ obj-$(CONFIG_SOC_OMAP5) += omap_hwmod_54xx_data.o obj-$(CONFIG_SOC_DRA7XX) += omap_hwmod_7xx_data.o # EMU peripherals +obj-$(CONFIG_OMAP3_EMU) += emu.o obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o diff --git a/arch/arm/mach-omap2/emu.c b/arch/arm/mach-omap2/emu.c new file mode 100644 index 000000000000..cbeaca2d7695 --- /dev/null +++ b/arch/arm/mach-omap2/emu.c @@ -0,0 +1,50 @@ +/* + * emu.c + * + * ETM and ETB CoreSight components' resources as found in OMAP3xxx. + * + * Copyright (C) 2009 Nokia Corporation. + * Alexander Shishkin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/amba/bus.h> +#include <linux/io.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include "soc.h" +#include "iomap.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexander Shishkin"); + +/* Cortex CoreSight components within omap3xxx EMU */ +#define ETM_BASE (L4_EMU_34XX_PHYS + 0x10000) +#define DBG_BASE (L4_EMU_34XX_PHYS + 0x11000) +#define ETB_BASE (L4_EMU_34XX_PHYS + 0x1b000) +#define DAPCTL (L4_EMU_34XX_PHYS + 0x1d000) + +static AMBA_APB_DEVICE(omap3_etb, "etb", 0x000bb907, ETB_BASE, { }, NULL); +static AMBA_APB_DEVICE(omap3_etm, "etm", 0x102bb921, ETM_BASE, { }, NULL); + +static int __init emu_init(void) +{ + if (!cpu_is_omap34xx()) + return -ENODEV; + + amba_device_register(&omap3_etb_device, &iomem_resource); + amba_device_register(&omap3_etm_device, &iomem_resource); + + return 0; +} + +omap_subsys_initcall(emu_init); diff --git a/linaro/configs/android.conf b/linaro/configs/android.conf deleted file mode 100644 index e4fd1ad19028..000000000000 --- a/linaro/configs/android.conf +++ /dev/null @@ -1,42 +0,0 @@ -CONFIG_IPV6=y -# CONFIG_IPV6_SIT is not set -CONFIG_PANIC_TIMEOUT=0 -CONFIG_HAS_WAKELOCK=y -CONFIG_WAKELOCK=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_DM_CRYPT=y -CONFIG_POWER_SUPPLY=y -CONFIG_ANDROID_PARANOID_NETWORK=y -CONFIG_NET_ACTIVITY_STATS=y -CONFIG_INPUT_MISC=y -CONFIG_INPUT_UINPUT=y -CONFIG_INPUT_GPIO=y -CONFIG_USB_G_ANDROID=y -CONFIG_SWITCH=y -CONFIG_STAGING=y -CONFIG_ANDROID=y -CONFIG_ANDROID_BINDER_IPC=y -CONFIG_ASHMEM=y -CONFIG_ANDROID_LOGGER=y -CONFIG_ANDROID_TIMED_OUTPUT=y -CONFIG_ANDROID_TIMED_GPIO=y -CONFIG_ANDROID_LOW_MEMORY_KILLER=y -CONFIG_ANDROID_INTF_ALARM_DEV=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=16384 -CONFIG_FUSE_FS=y -CONFIG_CPU_FREQ_GOV_INTERACTIVE=y -CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y -CONFIG_ION=y -CONFIG_SYNC=y -CONFIG_SW_SYNC=y -CONFIG_SW_SYNC_USER=y -CONFIG_ION_TEST=y -CONFIG_ION_DUMMY=y -CONFIG_ADF=y -CONFIG_ADF_FBDEV=y -CONFIG_ADF_MEMBLOCK=y -CONFIG_DMA_SHARED_BUFFER=y -CONFIG_TUN=y diff --git a/linaro/configs/preempt-rt.conf b/linaro/configs/preempt-rt.conf index 98e036d75442..7c6594f3a016 100644 --- a/linaro/configs/preempt-rt.conf +++ b/linaro/configs/preempt-rt.conf @@ -1,4 +1,3 @@ CONFIG_PREEMPT=y CONFIG_PREEMPT_RT_FULL=y -CONFIG_SLUB=y # CONFIG_CPU_FREQ is not set |