From: Arve Hjønnevåg Date: Tue, 3 Apr 2012 00:20:32 +0000 (-0700) Subject: ARM: etm: Add sysfs entry to enable timestamps if supported X-Git-Tag: v3.0.35-fsl~431 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=73b26602b3e008d6656a223d3aa453f58e777e61;p=karo-tx-linux.git ARM: etm: Add sysfs entry to enable timestamps if supported Change-Id: Iff964ba2f6236ed81863e02ec7b3ec9fbc48044a Signed-off-by: Arve Hjønnevåg --- diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h index 0fad8f8aed7d..42059d36f3aa 100644 --- a/arch/arm/include/asm/hardware/coresight.h +++ b/arch/arm/include/asm/hardware/coresight.h @@ -18,10 +18,12 @@ #define TRACER_RUNNING_BIT 1 #define TRACER_CYCLE_ACC_BIT 2 #define TRACER_TRACE_DATA_BIT 3 +#define TRACER_TIMESTAMP_BIT 4 #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_TRACE_DATA BIT(TRACER_TRACE_DATA_BIT) +#define TRACER_TIMESTAMP BIT(TRACER_TIMESTAMP_BIT) #define TRACER_TIMEOUT 10000 @@ -57,6 +59,7 @@ #define ETMCTRL_DATA_DO_BOTH (ETMCTRL_DATA_DO_DATA | ETMCTRL_DATA_DO_ADDR) #define ETMCTRL_BRANCH_OUTPUT (1 << 8) #define ETMCTRL_CYCLEACCURATE (1 << 12) +#define ETMCTRL_TIMESTAMP_EN (1 << 28) /* ETM configuration code register */ #define ETMR_CONFCODE (0x04) @@ -129,8 +132,12 @@ #define ETMR_ID 0x1e4 #define ETMIDR_VERSION(x) (((x) >> 4) & 0xff) +#define ETMIDR_VERSION_3_1 0x21 #define ETMIDR_VERSION_PFT_1_0 0x30 +#define ETMR_CCE 0x1e8 +#define ETMCCER_TIMESTAMPING_IMPLEMENTED BIT(22) + #define ETMR_TRACEIDR 0x200 /* ETM management registers, "ETM Architecture", 3.5.24 */ diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c index 9cdbb6d2a4e1..d83ba792dced 100644 --- a/arch/arm/kernel/etm.c +++ b/arch/arm/kernel/etm.c @@ -115,6 +115,9 @@ static int trace_start_etm(struct tracectx *t, int id) if (t->flags & TRACER_TRACE_DATA) v |= ETMCTRL_DATA_DO_ADDR; + if (t->flags & TRACER_TIMESTAMP) + v |= ETMCTRL_TIMESTAMP_EN; + etm_unlock(t, id); etm_writel(t, id, v, ETMR_CTRL); @@ -646,6 +649,36 @@ static ssize_t trace_mode_store(struct kobject *kobj, static struct kobj_attribute trace_mode_attr = __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store); +static ssize_t trace_timestamp_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_TIMESTAMP)); +} + +static ssize_t trace_timestamp_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t n) +{ + unsigned int timestamp; + + if (sscanf(buf, "%u", ×tamp) != 1) + return -EINVAL; + + mutex_lock(&tracer.mutex); + if (timestamp) + tracer.flags |= TRACER_TIMESTAMP; + else + tracer.flags &= ~TRACER_TIMESTAMP; + mutex_unlock(&tracer.mutex); + + return n; +} + +static struct kobj_attribute trace_timestamp_attr = + __ATTR(trace_timestamp, 0644, + trace_timestamp_show, trace_timestamp_store); + static ssize_t trace_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -725,6 +758,7 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id int new_count; u32 etmccr; u32 etmidr; + u32 etmccer = 0; u8 etm_version = 0; mutex_lock(&t->mutex); @@ -765,6 +799,8 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id if (etmccr & ETMCCR_ETMIDR_PRESENT) { etmidr = etm_readl(t, t->etm_regs_count, ETMR_ID); etm_version = ETMIDR_VERSION(etmidr); + if (etm_version >= ETMIDR_VERSION_3_1) + etmccer = etm_readl(t, t->etm_regs_count, ETMR_CCE); } etm_writel(t, t->etm_regs_count, 0x441, ETMR_CTRL); etm_writel(t, t->etm_regs_count, new_count, ETMR_TRACEIDR); @@ -784,6 +820,14 @@ static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id if (ret) dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n"); + if (etmccer & ETMCCER_TIMESTAMPING_IMPLEMENTED) { + ret = sysfs_create_file(&dev->dev.kobj, + &trace_timestamp_attr.attr); + if (ret) + dev_dbg(&dev->dev, + "Failed to create trace_timestamp in sysfs\n"); + } + ret = sysfs_create_file(&dev->dev.kobj, &trace_range_attr.attr); if (ret) dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");