Commit 35e1c916 authored by Suzuki K Poulose's avatar Suzuki K Poulose Committed by Mathieu Poirier

coresight: ete: Add support for ETE tracing

Add ETE as one of the supported device types we support
with ETM4x driver. The devices are named following the
existing convention as ete<N>.

ETE mandates that the trace resource status register is programmed
before the tracing is turned on. For the moment simply write to
it indicating TraceActive.

Cc: Mike Leach <mike.leach@linaro.org>
Reviewed-by: default avatarMike Leach <mike.leach@linaro.org>
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20210405164307.1720226-14-suzuki.poulose@arm.comSigned-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
parent 3e666ad0
...@@ -97,15 +97,15 @@ config CORESIGHT_SOURCE_ETM3X ...@@ -97,15 +97,15 @@ config CORESIGHT_SOURCE_ETM3X
module will be called coresight-etm3x. module will be called coresight-etm3x.
config CORESIGHT_SOURCE_ETM4X config CORESIGHT_SOURCE_ETM4X
tristate "CoreSight Embedded Trace Macrocell 4.x driver" tristate "CoreSight ETMv4.x / ETE driver"
depends on ARM64 depends on ARM64
select CORESIGHT_LINKS_AND_SINKS select CORESIGHT_LINKS_AND_SINKS
select PID_IN_CONTEXTIDR select PID_IN_CONTEXTIDR
help help
This driver provides support for the ETM4.x tracer module, tracing the This driver provides support for the CoreSight Embedded Trace Macrocell
instructions that a processor is executing. This is primarily useful version 4.x and the Embedded Trace Extensions (ETE). Both are CPU tracer
for instruction level tracing. Depending on the implemented version modules, tracing the instructions that a processor is executing. This is
data tracing may also be available. primarily useful for instruction level tracing.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called coresight-etm4x. module will be called coresight-etm4x.
......
...@@ -433,6 +433,13 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) ...@@ -433,6 +433,13 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR); etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
} }
/*
* ETE mandates that the TRCRSR is written to before
* enabling it.
*/
if (etm4x_is_ete(drvdata))
etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
/* Enable the trace unit */ /* Enable the trace unit */
etm4x_relaxed_write32(csa, 1, TRCPRGCTLR); etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
...@@ -894,13 +901,24 @@ static bool etm4_init_sysreg_access(struct etmv4_drvdata *drvdata, ...@@ -894,13 +901,24 @@ static bool etm4_init_sysreg_access(struct etmv4_drvdata *drvdata,
* ETMs implementing sysreg access must implement TRCDEVARCH. * ETMs implementing sysreg access must implement TRCDEVARCH.
*/ */
devarch = read_etm4x_sysreg_const_offset(TRCDEVARCH); devarch = read_etm4x_sysreg_const_offset(TRCDEVARCH);
if ((devarch & ETM_DEVARCH_ID_MASK) != ETM_DEVARCH_ETMv4x_ARCH) switch (devarch & ETM_DEVARCH_ID_MASK) {
case ETM_DEVARCH_ETMv4x_ARCH:
*csa = (struct csdev_access) {
.io_mem = false,
.read = etm4x_sysreg_read,
.write = etm4x_sysreg_write,
};
break;
case ETM_DEVARCH_ETE_ARCH:
*csa = (struct csdev_access) {
.io_mem = false,
.read = ete_sysreg_read,
.write = ete_sysreg_write,
};
break;
default:
return false; return false;
*csa = (struct csdev_access) { }
.io_mem = false,
.read = etm4x_sysreg_read,
.write = etm4x_sysreg_write,
};
drvdata->arch = etm_devarch_to_arch(devarch); drvdata->arch = etm_devarch_to_arch(devarch);
return true; return true;
...@@ -1841,6 +1859,8 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid) ...@@ -1841,6 +1859,8 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
struct etmv4_drvdata *drvdata; struct etmv4_drvdata *drvdata;
struct coresight_desc desc = { 0 }; struct coresight_desc desc = { 0 };
struct etm4_init_arg init_arg = { 0 }; struct etm4_init_arg init_arg = { 0 };
u8 major, minor;
char *type_name;
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata) if (!drvdata)
...@@ -1867,10 +1887,6 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid) ...@@ -1867,10 +1887,6 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
if (drvdata->cpu < 0) if (drvdata->cpu < 0)
return drvdata->cpu; return drvdata->cpu;
desc.name = devm_kasprintf(dev, GFP_KERNEL, "etm%d", drvdata->cpu);
if (!desc.name)
return -ENOMEM;
init_arg.drvdata = drvdata; init_arg.drvdata = drvdata;
init_arg.csa = &desc.access; init_arg.csa = &desc.access;
init_arg.pid = etm_pid; init_arg.pid = etm_pid;
...@@ -1887,6 +1903,22 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid) ...@@ -1887,6 +1903,22 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up")) fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up"))
drvdata->skip_power_up = true; drvdata->skip_power_up = true;
major = ETM_ARCH_MAJOR_VERSION(drvdata->arch);
minor = ETM_ARCH_MINOR_VERSION(drvdata->arch);
if (etm4x_is_ete(drvdata)) {
type_name = "ete";
/* ETE v1 has major version == 0b101. Adjust this for logging.*/
major -= 4;
} else {
type_name = "etm";
}
desc.name = devm_kasprintf(dev, GFP_KERNEL,
"%s%d", type_name, drvdata->cpu);
if (!desc.name)
return -ENOMEM;
etm4_init_trace_id(drvdata); etm4_init_trace_id(drvdata);
etm4_set_default(&drvdata->config); etm4_set_default(&drvdata->config);
...@@ -1914,9 +1946,8 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid) ...@@ -1914,9 +1946,8 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
etmdrvdata[drvdata->cpu] = drvdata; etmdrvdata[drvdata->cpu] = drvdata;
dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n", dev_info(&drvdata->csdev->dev, "CPU%d: %s v%d.%d initialized\n",
drvdata->cpu, ETM_ARCH_MAJOR_VERSION(drvdata->arch), drvdata->cpu, type_name, major, minor);
ETM_ARCH_MINOR_VERSION(drvdata->arch));
if (boot_enable) { if (boot_enable) {
coresight_enable(drvdata->csdev); coresight_enable(drvdata->csdev);
...@@ -2059,6 +2090,7 @@ static struct amba_driver etm4x_amba_driver = { ...@@ -2059,6 +2090,7 @@ static struct amba_driver etm4x_amba_driver = {
static const struct of_device_id etm4_sysreg_match[] = { static const struct of_device_id etm4_sysreg_match[] = {
{ .compatible = "arm,coresight-etm4x-sysreg" }, { .compatible = "arm,coresight-etm4x-sysreg" },
{ .compatible = "arm,embedded-trace-extension" },
{} {}
}; };
......
...@@ -2374,12 +2374,20 @@ static inline bool ...@@ -2374,12 +2374,20 @@ static inline bool
etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset) etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
{ {
switch (offset) { switch (offset) {
ETM4x_SYSREG_LIST_CASES ETM_COMMON_SYSREG_LIST_CASES
/* /*
* Registers accessible via system instructions are always * Common registers to ETE & ETM4x accessible via system
* implemented. * instructions are always implemented.
*/ */
return true; return true;
ETM4x_ONLY_SYSREG_LIST_CASES
/*
* We only support etm4x and ete. So if the device is not
* ETE, it must be ETMv4x.
*/
return !etm4x_is_ete(drvdata);
ETM4x_MMAP_LIST_CASES ETM4x_MMAP_LIST_CASES
/* /*
* Registers accessible only via memory-mapped registers * Registers accessible only via memory-mapped registers
...@@ -2389,8 +2397,13 @@ etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset) ...@@ -2389,8 +2397,13 @@ etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
* coresight_register() and the csdev is not initialized * coresight_register() and the csdev is not initialized
* until that is done. So rely on the drvdata->base to * until that is done. So rely on the drvdata->base to
* detect if we have a memory mapped access. * detect if we have a memory mapped access.
* Also ETE doesn't implement memory mapped access, thus
* it is sufficient to check that we are using mmio.
*/ */
return !!drvdata->base; return !!drvdata->base;
ETE_ONLY_SYSREG_LIST_CASES
return etm4x_is_ete(drvdata);
} }
return false; return false;
......
...@@ -128,6 +128,8 @@ ...@@ -128,6 +128,8 @@
#define TRCCIDR2 0xFF8 #define TRCCIDR2 0xFF8
#define TRCCIDR3 0xFFC #define TRCCIDR3 0xFFC
#define TRCRSR_TA BIT(12)
/* /*
* System instructions to access ETM registers. * System instructions to access ETM registers.
* See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions * See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions
...@@ -591,11 +593,14 @@ ...@@ -591,11 +593,14 @@
((ETM_DEVARCH_MAKE_ARCHID_ARCH_VER(major)) | ETM_DEVARCH_ARCHID_ARCH_PART(0xA13)) ((ETM_DEVARCH_MAKE_ARCHID_ARCH_VER(major)) | ETM_DEVARCH_ARCHID_ARCH_PART(0xA13))
#define ETM_DEVARCH_ARCHID_ETMv4x ETM_DEVARCH_MAKE_ARCHID(0x4) #define ETM_DEVARCH_ARCHID_ETMv4x ETM_DEVARCH_MAKE_ARCHID(0x4)
#define ETM_DEVARCH_ARCHID_ETE ETM_DEVARCH_MAKE_ARCHID(0x5)
#define ETM_DEVARCH_ID_MASK \ #define ETM_DEVARCH_ID_MASK \
(ETM_DEVARCH_ARCHITECT_MASK | ETM_DEVARCH_ARCHID_MASK | ETM_DEVARCH_PRESENT) (ETM_DEVARCH_ARCHITECT_MASK | ETM_DEVARCH_ARCHID_MASK | ETM_DEVARCH_PRESENT)
#define ETM_DEVARCH_ETMv4x_ARCH \ #define ETM_DEVARCH_ETMv4x_ARCH \
(ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETMv4x | ETM_DEVARCH_PRESENT) (ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETMv4x | ETM_DEVARCH_PRESENT)
#define ETM_DEVARCH_ETE_ARCH \
(ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETE | ETM_DEVARCH_PRESENT)
#define TRCSTATR_IDLE_BIT 0 #define TRCSTATR_IDLE_BIT 0
#define TRCSTATR_PMSTABLE_BIT 1 #define TRCSTATR_PMSTABLE_BIT 1
...@@ -685,6 +690,8 @@ ...@@ -685,6 +690,8 @@
#define ETM_ARCH_MINOR_VERSION(arch) ((arch) & 0xfU) #define ETM_ARCH_MINOR_VERSION(arch) ((arch) & 0xfU)
#define ETM_ARCH_V4 ETM_ARCH_VERSION(4, 0) #define ETM_ARCH_V4 ETM_ARCH_VERSION(4, 0)
#define ETM_ARCH_ETE ETM_ARCH_VERSION(5, 0)
/* Interpretation of resource numbers change at ETM v4.3 architecture */ /* Interpretation of resource numbers change at ETM v4.3 architecture */
#define ETM_ARCH_V4_3 ETM_ARCH_VERSION(4, 3) #define ETM_ARCH_V4_3 ETM_ARCH_VERSION(4, 3)
...@@ -993,4 +1000,9 @@ void etm4_config_trace_mode(struct etmv4_config *config); ...@@ -993,4 +1000,9 @@ void etm4_config_trace_mode(struct etmv4_config *config);
u64 etm4x_sysreg_read(u32 offset, bool _relaxed, bool _64bit); u64 etm4x_sysreg_read(u32 offset, bool _relaxed, bool _64bit);
void etm4x_sysreg_write(u64 val, u32 offset, bool _relaxed, bool _64bit); void etm4x_sysreg_write(u64 val, u32 offset, bool _relaxed, bool _64bit);
static inline bool etm4x_is_ete(struct etmv4_drvdata *drvdata)
{
return drvdata->arch >= ETM_ARCH_ETE;
}
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment