* +--------------+
* |
* +------v-------+
- * | Counter x | (reload to 1 on underflow)
+ * | Counter x | (reload to 2 ^ (ts_level - 1) on underflow)
* +--------------+
* |
* +------v--------------+
* | Timestamp Generator | (timestamp on resource y)
* +----------------------+
*/
-static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)
+static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata,
+ u8 ts_level)
{
int ctridx;
int rselector;
return -ENOSPC;
}
- /*
- * Initialise original and reload counter value to the smallest
- * possible value in order to get as much precision as we can.
- */
- config->cntr_val[ctridx] = 1;
- config->cntrldvr[ctridx] = 1;
+ /* Initialise original and reload counter value. */
+ config->cntr_val[ctridx] = config->cntrldvr[ctridx] = 1 << (ts_level - 1);
/*
* Trace Counter Control Register TRCCNTCTLRn
struct perf_event_attr *attr = &event->attr;
unsigned long cfg_hash;
int preset, cc_threshold;
+ u8 ts_level;
/* Clear configuration from previous run */
memset(config, 0, sizeof(struct etmv4_config));
cc_threshold = drvdata->ccitmin;
config->ccctlr = cc_threshold;
}
- if (ATTR_CFG_GET_FLD(attr, timestamp)) {
+
+ ts_level = ATTR_CFG_GET_FLD(attr, timestamp);
+ if (ts_level) {
/*
* Configure timestamps to be emitted at regular intervals in
* order to correlate instructions executed on different CPUs
* (CPU-wide trace scenarios).
*/
- ret = etm4_config_timestamp_event(drvdata);
+ ret = etm4_config_timestamp_event(drvdata, ts_level);
/*
* No need to go further if timestamp intervals can't