HI Leo,
On Wed, 28 Aug 2019 at 06:18, Leo Yan leo.yan@linaro.org wrote:
On Mon, Aug 19, 2019 at 09:57:19PM +0100, Mike Leach wrote:
An API to control single-shot comparator operation was missing from sysfs. This adds the parameters to sysfs to allow programming of this feature.
Signed-off-by: Mike Leach mike.leach@linaro.org
.../coresight/coresight-etm4x-sysfs.c | 122 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-etm4x.c | 26 +++- drivers/hwtracing/coresight/coresight-etm4x.h | 3 + 3 files changed, 150 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index 483976074779..7c019dda1236 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -239,6 +239,7 @@ static ssize_t reset_store(struct device *dev, for (i = 0; i < drvdata->nr_resource; i++) config->res_ctrl[i] = 0x0;
config->ss_idx = 0x0; for (i = 0; i < drvdata->nr_ss_cmp; i++) { config->ss_ctrl[i] = 0x0; config->ss_pe_cmp[i] = 0x0;
@@ -1713,6 +1714,123 @@ static ssize_t res_ctrl_store(struct device *dev, } static DEVICE_ATTR_RW(res_ctrl);
+static ssize_t sshot_idx_show(struct device *dev,
struct device_attribute *attr, char *buf)
+{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
val = config->ss_idx;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static ssize_t sshot_idx_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
+{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
if (val >= drvdata->nr_ss_cmp)
return -EINVAL;
spin_lock(&drvdata->spinlock);
config->ss_idx = val;
spin_unlock(&drvdata->spinlock);
return size;
+} +static DEVICE_ATTR_RW(sshot_idx);
+static ssize_t sshot_ctrl_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
spin_lock(&drvdata->spinlock);
val = config->ss_ctrl[config->ss_idx];
spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static ssize_t sshot_ctrl_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
+{
u8 idx;
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
spin_lock(&drvdata->spinlock);
idx = config->ss_idx;
config->ss_ctrl[idx] = val & GENMASK(24, 0);
/* must clear bit 31 in related status register on programming */
config->ss_status[idx] &= ~BIT(31);
Since function etm4_enable_hw() will clear ss_status's bit 31 when program TRCSSCSRn, so is here redundant to clear bit 31?
spin_unlock(&drvdata->spinlock);
return size;
+} +static DEVICE_ATTR_RW(sshot_ctrl);
+static ssize_t sshot_status_show(struct device *dev,
struct device_attribute *attr, char *buf)
+{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
spin_lock(&drvdata->spinlock);
val = config->ss_status[config->ss_idx];
spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+} +static DEVICE_ATTR_RO(sshot_status);
+static ssize_t sshot_pe_ctrl_show(struct device *dev,
struct device_attribute *attr,
char *buf)
+{
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
spin_lock(&drvdata->spinlock);
val = config->ss_pe_cmp[config->ss_idx];
spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static ssize_t sshot_pe_ctrl_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
+{
u8 idx;
unsigned long val;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct etmv4_config *config = &drvdata->config;
if (kstrtoul(buf, 16, &val))
return -EINVAL;
spin_lock(&drvdata->spinlock);
idx = config->ss_idx;
config->ss_ctrl[idx] = val & GENMASK(7, 0);
/* must clear bit 31 in related status register on programming */
config->ss_status[idx] &= ~BIT(31);
Same question for if it's redundant to clear bit 31?
Thanks, Leo Yan
The sysfs representation is not the current state of these registers, but the values that will be programmed on enabling the hardware. We do not write anything to hardware immediately. So from a sysfs perspective, the bit clear is reflected in the status register here to recognise that it will be programmed as cleared.
Should the same registers be set from a different path - e.g. perf, then the status will automatically be cleared each time the hw is enabled.
Regards
Mike
spin_unlock(&drvdata->spinlock);
return size;
+} +static DEVICE_ATTR_RW(sshot_pe_ctrl);
static ssize_t ctxid_idx_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -2169,6 +2287,10 @@ static struct attribute *coresight_etmv4_attrs[] = { &dev_attr_addr_exlevel_s_ns.attr, &dev_attr_addr_cmp_view.attr, &dev_attr_vinst_pe_cmp_start_stop.attr,
&dev_attr_sshot_idx.attr,
&dev_attr_sshot_ctrl.attr,
&dev_attr_sshot_pe_ctrl.attr,
&dev_attr_sshot_status.attr, &dev_attr_seq_idx.attr, &dev_attr_seq_state.attr, &dev_attr_seq_event.attr,
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index d8b078d0cc7f..fb7083218410 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -149,6 +149,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) drvdata->base + TRCRSCTLRn(i));
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
/* always clear status bit on restart if using single-shot */
if (config->ss_ctrl[i] || config->ss_pe_cmp[i])
config->ss_status[i] &= ~BIT(31); writel_relaxed(config->ss_ctrl[i], drvdata->base + TRCSSCCRn(i)); writel_relaxed(config->ss_status[i],
@@ -448,6 +451,9 @@ static void etm4_disable_hw(void *info) { u32 control; struct etmv4_drvdata *drvdata = info;
struct etmv4_config *config = &drvdata->config;
struct device *etm_dev = &drvdata->csdev->dev;
int i; CS_UNLOCK(drvdata->base);
@@ -470,6 +476,18 @@ static void etm4_disable_hw(void *info) isb(); writel_relaxed(control, drvdata->base + TRCPRGCTLR);
/* wait for TRCSTATR.PMSTABLE to go to '1' */
if (coresight_timeout(drvdata->base, TRCSTATR,
TRCSTATR_PMSTABLE_BIT, 1))
dev_err(etm_dev,
"timeout while waiting for PM stable Trace Status\n");
/* read the status of the single shot comparators */
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
config->ss_status[i] =
readl_relaxed(drvdata->base + TRCSSCSRn(i));
}
coresight_disclaim_device_unlocked(drvdata->base); CS_LOCK(drvdata->base);
@@ -576,6 +594,7 @@ static void etm4_init_arch_data(void *info) u32 etmidr4; u32 etmidr5; struct etmv4_drvdata *drvdata = info;
int i; /* Make sure all registers are accessible */ etm4_os_unlock(drvdata);
@@ -699,9 +718,14 @@ static void etm4_init_arch_data(void *info) drvdata->nr_resource = BMVAL(etmidr4, 16, 19) + 1; /* * NUMSSCC, bits[23:20] the number of single-shot
* comparator control for tracing
* comparator control for tracing. Read any status regs as these
* also contain RO capability data. */ drvdata->nr_ss_cmp = BMVAL(etmidr4, 20, 23);
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
drvdata->config.ss_status[i] =
readl_relaxed(drvdata->base + TRCSSCSRn(i));
} /* NUMCIDC, bits[27:24] number of Context ID comparators for tracing */ drvdata->numcidc = BMVAL(etmidr4, 24, 27); /* NUMVMIDC, bits[31:28] number of VMID comparators for tracing */
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 60bc2fb5159b..be8b32ea1654 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -175,6 +175,7 @@ ETM_MODE_EXCL_USER)
#define TRCSTATR_IDLE_BIT 0 +#define TRCSTATR_PMSTABLE_BIT 1 #define ETM_DEFAULT_ADDR_COMP 0
/* PowerDown Control Register bits */ @@ -226,6 +227,7 @@
- @cntr_val: Sets or returns the value for a counter.
- @res_idx: Resource index selector.
- @res_ctrl: Controls the selection of the resources in the trace unit.
- @ss_idx: Single-shot index selector.
- @ss_ctrl: Controls the corresponding single-shot comparator resource.
- @ss_status: The status of the corresponding single-shot comparator.
- @ss_pe_cmp: Selects the PE comparator inputs for Single-shot control.
@@ -269,6 +271,7 @@ struct etmv4_config { u32 cntr_val[ETMv4_MAX_CNTR]; u8 res_idx; u32 res_ctrl[ETM_MAX_RES_SEL];
u8 ss_idx; u32 ss_ctrl[ETM_MAX_SS_CMP]; u32 ss_status[ETM_MAX_SS_CMP]; u32 ss_pe_cmp[ETM_MAX_SS_CMP];
-- 2.17.1
CoreSight mailing list CoreSight@lists.linaro.org https://lists.linaro.org/mailman/listinfo/coresight