coresight: fix handling of ETM trace register access via sysfs
authorSudeep Holla <sudeep.holla@arm.com>
Thu, 25 Aug 2016 21:19:09 +0000 (15:19 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Aug 2016 11:05:43 +0000 (13:05 +0200)
The ETM registers are classified into 2 categories: trace and management.
The core power domain contains most of the trace unit logic including
all(except TRCOSLAR and TRCOSLSR) the trace registers. The debug power
domain contains the external debugger interface including all management
registers.

This patch adds coresight unit specific function coresight_simple_func
which can be used for ETM trace registers by providing a ETM specific
read function which does smp cross call to ensure the trace core is
powered up before the register is accessed.

Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/hwtracing/coresight/coresight-etb10.c
drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
drivers/hwtracing/coresight/coresight-priv.h
drivers/hwtracing/coresight/coresight-stm.c
drivers/hwtracing/coresight/coresight-tmc.c

index 8a4927ca9181c334881616e16dd5a8f761c5a904..d7325c6534ad9d96e899fce16ddb6fa2e6148c4b 100644 (file)
@@ -559,7 +559,7 @@ static const struct file_operations etb_fops = {
 };
 
 #define coresight_etb10_simple_func(name, offset)                       \
-       coresight_simple_func(struct etb_drvdata, name, offset)
+       coresight_simple_func(struct etb_drvdata, NULL, name, offset)
 
 coresight_etb10_simple_func(rdp, ETB_RAM_DEPTH_REG);
 coresight_etb10_simple_func(sts, ETB_STATUS_REG);
index 02d4b629891f4a198b72a44910f18fa45abe1535..4856c809841627c0a6c29845b3d4cc73fbb6f5e9 100644 (file)
@@ -1222,7 +1222,7 @@ static struct attribute *coresight_etm_attrs[] = {
 };
 
 #define coresight_etm3x_simple_func(name, offset)                      \
-       coresight_simple_func(struct etm_drvdata, name, offset)
+       coresight_simple_func(struct etm_drvdata, NULL, name, offset)
 
 coresight_etm3x_simple_func(etmccr, ETMCCR);
 coresight_etm3x_simple_func(etmccer, ETMCCER);
index 7c84308c55643440486517d26ca58b908e31188d..fd7ff613db1713a703f056a01f51b6cc722079f7 100644 (file)
@@ -2039,15 +2039,42 @@ static struct attribute *coresight_etmv4_attrs[] = {
        NULL,
 };
 
+struct etmv4_reg {
+       void __iomem *addr;
+       u32 data;
+};
+
+static void do_smp_cross_read(void *data)
+{
+       struct etmv4_reg *reg = data;
+
+       reg->data = readl_relaxed(reg->addr);
+}
+
+static u32 etmv4_cross_read(const struct device *dev, u32 offset)
+{
+       struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
+       struct etmv4_reg reg;
+
+       reg.addr = drvdata->base + offset;
+       /*
+        * smp cross call ensures the CPU will be powered up before
+        * accessing the ETMv4 trace core registers
+        */
+       smp_call_function_single(drvdata->cpu, do_smp_cross_read, &reg, 1);
+       return reg.data;
+}
+
 #define coresight_etm4x_simple_func(name, offset)                      \
-       coresight_simple_func(struct etmv4_drvdata, name, offset)
+       coresight_simple_func(struct etmv4_drvdata, NULL, name, offset)
+
+#define coresight_etm4x_cross_read(name, offset)                       \
+       coresight_simple_func(struct etmv4_drvdata, etmv4_cross_read,   \
+                             name, offset)
 
-coresight_etm4x_simple_func(trcoslsr, TRCOSLSR);
 coresight_etm4x_simple_func(trcpdcr, TRCPDCR);
 coresight_etm4x_simple_func(trcpdsr, TRCPDSR);
 coresight_etm4x_simple_func(trclsr, TRCLSR);
-coresight_etm4x_simple_func(trcconfig, TRCCONFIGR);
-coresight_etm4x_simple_func(trctraceid, TRCTRACEIDR);
 coresight_etm4x_simple_func(trcauthstatus, TRCAUTHSTATUS);
 coresight_etm4x_simple_func(trcdevid, TRCDEVID);
 coresight_etm4x_simple_func(trcdevtype, TRCDEVTYPE);
@@ -2055,6 +2082,9 @@ coresight_etm4x_simple_func(trcpidr0, TRCPIDR0);
 coresight_etm4x_simple_func(trcpidr1, TRCPIDR1);
 coresight_etm4x_simple_func(trcpidr2, TRCPIDR2);
 coresight_etm4x_simple_func(trcpidr3, TRCPIDR3);
+coresight_etm4x_cross_read(trcoslsr, TRCOSLSR);
+coresight_etm4x_cross_read(trcconfig, TRCCONFIGR);
+coresight_etm4x_cross_read(trctraceid, TRCTRACEIDR);
 
 static struct attribute *coresight_etmv4_mgmt_attrs[] = {
        &dev_attr_trcoslsr.attr,
@@ -2073,19 +2103,19 @@ static struct attribute *coresight_etmv4_mgmt_attrs[] = {
        NULL,
 };
 
-coresight_etm4x_simple_func(trcidr0, TRCIDR0);
-coresight_etm4x_simple_func(trcidr1, TRCIDR1);
-coresight_etm4x_simple_func(trcidr2, TRCIDR2);
-coresight_etm4x_simple_func(trcidr3, TRCIDR3);
-coresight_etm4x_simple_func(trcidr4, TRCIDR4);
-coresight_etm4x_simple_func(trcidr5, TRCIDR5);
+coresight_etm4x_cross_read(trcidr0, TRCIDR0);
+coresight_etm4x_cross_read(trcidr1, TRCIDR1);
+coresight_etm4x_cross_read(trcidr2, TRCIDR2);
+coresight_etm4x_cross_read(trcidr3, TRCIDR3);
+coresight_etm4x_cross_read(trcidr4, TRCIDR4);
+coresight_etm4x_cross_read(trcidr5, TRCIDR5);
 /* trcidr[6,7] are reserved */
-coresight_etm4x_simple_func(trcidr8, TRCIDR8);
-coresight_etm4x_simple_func(trcidr9, TRCIDR9);
-coresight_etm4x_simple_func(trcidr10, TRCIDR10);
-coresight_etm4x_simple_func(trcidr11, TRCIDR11);
-coresight_etm4x_simple_func(trcidr12, TRCIDR12);
-coresight_etm4x_simple_func(trcidr13, TRCIDR13);
+coresight_etm4x_cross_read(trcidr8, TRCIDR8);
+coresight_etm4x_cross_read(trcidr9, TRCIDR9);
+coresight_etm4x_cross_read(trcidr10, TRCIDR10);
+coresight_etm4x_cross_read(trcidr11, TRCIDR11);
+coresight_etm4x_cross_read(trcidr12, TRCIDR12);
+coresight_etm4x_cross_read(trcidr13, TRCIDR13);
 
 static struct attribute *coresight_etmv4_trcidr_attrs[] = {
        &dev_attr_trcidr0.attr,
index decfd52b5dc36d03fe9198e0cf43da9d625191b9..39841d1f58e02e786c0ca3fff7656e831e689964 100644 (file)
 #define ETM_MODE_EXCL_KERN     BIT(30)
 #define ETM_MODE_EXCL_USER     BIT(31)
 
-#define coresight_simple_func(type, name, offset)                      \
+typedef u32 (*coresight_read_fn)(const struct device *, u32 offset);
+#define coresight_simple_func(type, func, name, offset)                        \
 static ssize_t name##_show(struct device *_dev,                                \
                           struct device_attribute *attr, char *buf)    \
 {                                                                      \
        type *drvdata = dev_get_drvdata(_dev->parent);                  \
+       coresight_read_fn fn = func;                                    \
        u32 val;                                                        \
        pm_runtime_get_sync(_dev->parent);                              \
-       val = readl_relaxed(drvdata->base + offset);                    \
+       if (fn)                                                         \
+               val = fn(_dev->parent, offset);                         \
+       else                                                            \
+               val = readl_relaxed(drvdata->base + offset);            \
        pm_runtime_put_sync(_dev->parent);                              \
        return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);                \
 }                                                                      \
index 819629aed2f7d2a362e9437fd9de9b471154b108..7949f0f6744ae28edf118aaefed28d508ca66ad8 100644 (file)
@@ -635,7 +635,7 @@ static ssize_t traceid_store(struct device *dev,
 static DEVICE_ATTR_RW(traceid);
 
 #define coresight_stm_simple_func(name, offset)        \
-       coresight_simple_func(struct stm_drvdata, name, offset)
+       coresight_simple_func(struct stm_drvdata, NULL, name, offset)
 
 coresight_stm_simple_func(tcsr, STMTCSR);
 coresight_stm_simple_func(tsfreqr, STMTSFREQR);
index 4cbcaf93c9d999082d779db1bec499298bdc1061..a4748630f5d630e6df2fd13cf01af91f2f6da0e1 100644 (file)
@@ -218,7 +218,7 @@ static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid)
 }
 
 #define coresight_tmc_simple_func(name, offset)                        \
-       coresight_simple_func(struct tmc_drvdata, name, offset)
+       coresight_simple_func(struct tmc_drvdata, NULL, name, offset)
 
 coresight_tmc_simple_func(rsz, TMC_RSZ);
 coresight_tmc_simple_func(sts, TMC_STS);