#include <linux/clk.h>
#include <linux/cpu.h>
#include <linux/coresight.h>
+#include <linux/coresight-pmu.h>
#include <linux/pm_wakeup.h>
#include <linux/amba/bus.h>
#include <linux/seq_file.h>
CS_LOCK(drvdata->base);
}
-static void etm4_init_default_data(struct etmv4_drvdata *drvdata)
+static void etm4_set_default(struct etmv4_config *config)
{
- int i;
- struct etmv4_config *config = &drvdata->config;
+ if (WARN_ON_ONCE(!config))
+ return;
- config->pe_sel = 0x0;
- config->cfg = (ETMv4_MODE_CTXID | ETM_MODE_VMID |
- ETMv4_MODE_TIMESTAMP | ETM_MODE_RETURNSTACK);
+ /*
+ * Make default initialisation trace everything
+ *
+ * Select the "always true" resource selector on the
+ * "Enablign Event" line and configure address range comparator
+ * '0' to trace all the possible address range. From there
+ * configure the "include/exclude" engine to include address
+ * range comparator '0'.
+ */
/* disable all events tracing */
config->eventctrl0 = 0x0;
/* disable stalling */
config->stall_ctrl = 0x0;
+ /* enable trace synchronization every 4096 bytes, if available */
+ config->syncfreq = 0xC;
+
/* disable timestamp event */
config->ts_ctrl = 0x0;
- /* enable trace synchronization every 4096 bytes for trace */
- if (drvdata->syncpr == false)
- config->syncfreq = 0xC;
+ /* TRCVICTLR::EVENT = 0x01, select the always on logic */
+ config->vinst_ctrl |= BIT(0);
/*
- * enable viewInst to trace everything with start-stop logic in
- * started state
+ * TRCVICTLR::SSSTATUS == 1, the start-stop logic is
+ * in the started state
*/
- config->vinst_ctrl |= BIT(0);
- /* set initial state of start-stop logic */
- if (drvdata->nr_addr_cmp)
- config->vinst_ctrl |= BIT(9);
-
- /* no address range filtering for ViewInst */
- config->viiectlr = 0x0;
- /* no start-stop filtering for ViewInst */
- config->vissctlr = 0x0;
-
- /* disable seq events */
- for (i = 0; i < drvdata->nrseqstate-1; i++)
- config->seq_ctrl[i] = 0x0;
- config->seq_rst = 0x0;
- config->seq_state = 0x0;
-
- /* disable external input events */
- config->ext_inp = 0x0;
-
- for (i = 0; i < drvdata->nr_cntr; i++) {
- config->cntrldvr[i] = 0x0;
- config->cntr_ctrl[i] = 0x0;
- config->cntr_val[i] = 0x0;
- }
-
- /* Resource selector pair 0 is always implemented and reserved */
- config->res_idx = 0x2;
- for (i = 2; i < drvdata->nr_resource * 2; i++)
- config->res_ctrl[i] = 0x0;
+ config->vinst_ctrl |= BIT(9);
- for (i = 0; i < drvdata->nr_ss_cmp; i++) {
- config->ss_ctrl[i] = 0x0;
- config->ss_pe_cmp[i] = 0x0;
- }
-
- if (drvdata->nr_addr_cmp >= 1) {
- config->addr_val[0] = (unsigned long)_stext;
- config->addr_val[1] = (unsigned long)_etext;
- config->addr_type[0] = ETM_ADDR_TYPE_RANGE;
- config->addr_type[1] = ETM_ADDR_TYPE_RANGE;
- }
-
- for (i = 0; i < drvdata->numcidc; i++) {
- config->ctxid_pid[i] = 0x0;
- config->ctxid_vpid[i] = 0x0;
- }
+ /*
+ * Configure address range comparator '0' to encompass all
+ * possible addresses.
+ */
- config->ctxid_mask0 = 0x0;
- config->ctxid_mask1 = 0x0;
+ /* First half of default address comparator: start at address 0 */
+ config->addr_val[ETM_DEFAULT_ADDR_COMP] = 0x0;
+ /* trace instruction addresses */
+ config->addr_acc[ETM_DEFAULT_ADDR_COMP] &= ~(BIT(0) | BIT(1));
+ /* EXLEVEL_NS, bits[12:15], only trace application and kernel space */
+ config->addr_acc[ETM_DEFAULT_ADDR_COMP] |= ETM_EXLEVEL_NS_HYP;
+ /* EXLEVEL_S, bits[11:8], don't trace anything in secure state */
+ config->addr_acc[ETM_DEFAULT_ADDR_COMP] |= (ETM_EXLEVEL_S_APP |
+ ETM_EXLEVEL_S_OS |
+ ETM_EXLEVEL_S_HYP);
+ config->addr_type[ETM_DEFAULT_ADDR_COMP] = ETM_ADDR_TYPE_RANGE;
- for (i = 0; i < drvdata->numvmidc; i++)
- config->vmid_val[i] = 0x0;
- config->vmid_mask0 = 0x0;
- config->vmid_mask1 = 0x0;
+ /*
+ * Second half of default address comparator: go all
+ * the way to the top.
+ */
+ config->addr_val[ETM_DEFAULT_ADDR_COMP + 1] = ~0x0;
+ /* trace instruction addresses */
+ config->addr_acc[ETM_DEFAULT_ADDR_COMP + 1] &= ~(BIT(0) | BIT(1));
+ /* Address comparator type must be equal for both halves */
+ config->addr_acc[ETM_DEFAULT_ADDR_COMP + 1] =
+ config->addr_acc[ETM_DEFAULT_ADDR_COMP];
+ config->addr_type[ETM_DEFAULT_ADDR_COMP + 1] = ETM_ADDR_TYPE_RANGE;
/*
- * A trace ID value of 0 is invalid, so let's start at some
- * random value that fits in 7 bits. ETMv3.x has 0x10 so let's
- * start at 0x20.
+ * Configure the ViewInst function to filter on address range
+ * comparator '0'.
*/
- drvdata->trcid = 0x20 + drvdata->cpu;
+ config->viiectlr = BIT(0);
+
+ /* no start-stop filtering for ViewInst */
+ config->vissctlr = 0x0;
}
static int etm4_cpu_callback(struct notifier_block *nfb, unsigned long action,
.notifier_call = etm4_cpu_callback,
};
+static void etm4_init_trace_id(struct etmv4_drvdata *drvdata)
+{
+ drvdata->trcid = coresight_get_trace_id(drvdata->cpu);
+}
+
static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
{
int ret;
ret = -EINVAL;
goto err_arch_supported;
}
- etm4_init_default_data(drvdata);
+
+ etm4_init_trace_id(drvdata);
+ etm4_set_default(&drvdata->config);
pm_runtime_put(&adev->dev);