CoreSight ETMv4.4 introduced system instructions for accessing the ETM. This also implies that they may not be on the amba bus. Right now all the CoreSight components are accessed via memory map. Also, we have some common routines in coresight generic code driver (e.g, CS_LOCK, claim/disclaim), which assume the mmio. In order to preserve the generic algorithms at a single place and to allow dynamic switch for ETMs, this series introduces an abstraction layer for accessing a coresight device. It is designed such that the mmio access are fast tracked (i.e, without an indirect function call).
This will also help us to get rid of the driver+attribute specific sysfs show/store routines and replace them with a single routine to access a given register offset (which can be embedded in the dev_ext_attribute). This is not currently implemented in the series, but can be achieved.
Further we switch the generic routines to work with the abstraction. With this in place, we refactor the etm4x code a bit to allow for supporting the system instructions with very little new code. The changes also switch to using the system instructions by default even when we may have an MMIO.
We use TRCDEVARCH for the detection of the ETM component, which is a standard register as per CoreSight architecture, rather than the etm specific id register TRCIDR3. This is for making sure that we are able to detect the ETM via system instructions accurately, when the the trace unit could be anything (etm or a custom trace unit).
The series has been mildly tested on a model. I would really appreciate any testing on real hardware.
Applies on coresight/next
Changes since V1: - Flip the switch for iomem from no_iomem to io_mem in csdev_access. - Split patches for claim/disclaim and CS_LOCK/UNLOCK conversions. - Move device access initialisation for etm4x to the target CPU - Cleanup secure exception level mask handling. - Switch to use TRCDEVARCH for ETM component discovery. This is for making - Check the availability of OS/Software Locks before using them.
Suzuki K Poulose (19): coresight: Introduce device access abstraction coresight: tpiu: Prepare for using coresight device access abstraction coresight: Convert coresight_timeout to use access abstraction coresight: Convert claim/disclaim operations to use access wrappers coresight: Use device access layer for Software lock/unlock operations coresight: etm4x: Always read the registers on the host CPU coresight: etm4x: Convert all register accesses coresight: etm4x: Add commentary on the registers coresight: etm4x: Add sysreg access helpers coresight: etm4x: Define DEVARCH register fields coresight: etm4x: Check for OS and Software Lock coresight: etm4x: Cleanup secure exception level masks coresight: etm4x: Clean up exception level masks coresight: etm4x: Detect access early on the target CPU coresight: etm4x: Use TRCDEVARCH for component discovery coresight: etm4x: Detect system instructions support coresight: etm4x: Refactor probing routine coresight: etm4x: Add support for sysreg only devices dts: bindings: coresight: ETMv4.4 system register access only units
.../devicetree/bindings/arm/coresight.txt | 6 +- drivers/hwtracing/coresight/coresight-catu.c | 24 +- .../hwtracing/coresight/coresight-cpu-debug.c | 22 +- .../hwtracing/coresight/coresight-cti-sysfs.c | 5 +- drivers/hwtracing/coresight/coresight-cti.c | 34 +- drivers/hwtracing/coresight/coresight-etb10.c | 29 +- .../coresight/coresight-etm3x-sysfs.c | 10 +- drivers/hwtracing/coresight/coresight-etm3x.c | 35 +- .../coresight/coresight-etm4x-sysfs.c | 44 +- drivers/hwtracing/coresight/coresight-etm4x.c | 716 +++++++++++------- drivers/hwtracing/coresight/coresight-etm4x.h | 440 ++++++++++- .../hwtracing/coresight/coresight-funnel.c | 22 +- drivers/hwtracing/coresight/coresight-priv.h | 9 +- .../coresight/coresight-replicator.c | 31 +- drivers/hwtracing/coresight/coresight-stm.c | 50 +- .../hwtracing/coresight/coresight-tmc-etf.c | 38 +- .../hwtracing/coresight/coresight-tmc-etr.c | 20 +- drivers/hwtracing/coresight/coresight-tmc.c | 16 +- drivers/hwtracing/coresight/coresight-tpiu.c | 32 +- drivers/hwtracing/coresight/coresight.c | 130 +++- include/linux/coresight.h | 230 +++++- 21 files changed, 1449 insertions(+), 494 deletions(-)
We are about to introduce support for sysreg access to ETMv4.4+ component. Since there are generic routines that access the registers (e.g, CS_LOCK/UNLOCK , claim/disclaim operations, timeout) and in order to preserve the logic of these operations at a single place we introduce an abstraction layer for the accesses to a given device.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-catu.c | 1 + drivers/hwtracing/coresight/coresight-cti.c | 1 + drivers/hwtracing/coresight/coresight-etb10.c | 1 + drivers/hwtracing/coresight/coresight-etm3x.c | 1 + drivers/hwtracing/coresight/coresight-etm4x.c | 1 + .../hwtracing/coresight/coresight-funnel.c | 1 + .../coresight/coresight-replicator.c | 1 + drivers/hwtracing/coresight/coresight-stm.c | 1 + drivers/hwtracing/coresight/coresight-tmc.c | 1 + drivers/hwtracing/coresight/coresight-tpiu.c | 1 + drivers/hwtracing/coresight/coresight.c | 49 +++++ include/linux/coresight.h | 197 ++++++++++++++++++ 12 files changed, 256 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 1801804a7762..90da0b842717 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -551,6 +551,7 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id) dev->platform_data = pdata;
drvdata->base = base; + catu_desc.access = CSDEV_ACCESS_IOMEM(base); catu_desc.pdata = pdata; catu_desc.dev = dev; catu_desc.groups = catu_groups; diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index 47f3c9abae30..e13e24e4a858 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -849,6 +849,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base; + cti_desc.access = CSDEV_ACCESS_IOMEM(base);
dev_set_drvdata(dev, drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 03e3f2590191..42fe174a68f0 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -755,6 +755,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base; + desc.access = CSDEV_ACCESS_IOMEM(base);
spin_lock_init(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index bf22dcfd3327..e3724d8adecb 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -805,6 +805,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base; + desc.access = CSDEV_ACCESS_IOMEM(base);
spin_lock_init(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 00c9f0bb8b1a..466e6f304751 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1488,6 +1488,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base; + desc.access = CSDEV_ACCESS_IOMEM(base);
spin_lock_init(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 900690a9f7f0..e8e233cbc130 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -242,6 +242,7 @@ static int funnel_probe(struct device *dev, struct resource *res) } drvdata->base = base; desc.groups = coresight_funnel_groups; + desc.access = CSDEV_ACCESS_IOMEM(base); }
dev_set_drvdata(dev, drvdata); diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 78acf29c49ca..8ba9cbe1d108 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -254,6 +254,7 @@ static int replicator_probe(struct device *dev, struct resource *res) } drvdata->base = base; desc.groups = replicator_groups; + desc.access = CSDEV_ACCESS_IOMEM(base); }
if (fwnode_property_present(dev_fwnode(dev), diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 2ba819a47cf6..fbf86f31f2ab 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -884,6 +884,7 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id) if (IS_ERR(base)) return PTR_ERR(base); drvdata->base = base; + desc.access = CSDEV_ACCESS_IOMEM(base);
ret = stm_get_stimulus_area(dev, &ch_res); if (ret) diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 7040d583bed9..5711e55c310c 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -458,6 +458,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) }
drvdata->base = base; + desc.access = CSDEV_ACCESS_IOMEM(base);
spin_lock_init(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index f8583e4032a6..4eb3f50618b6 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -149,6 +149,7 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base; + desc.access = CSDEV_ACCESS_IOMEM(base);
/* Disable tpiu to support older devices */ tpiu_disable_hw(drvdata); diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index e9c90f2de34a..38e9c03ab754 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1387,6 +1387,54 @@ static int __init coresight_init(void) } postcore_initcall(coresight_init);
+u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset) +{ + return csdev_access_relaxed_read32(&csdev->access, offset); +} + +u32 coresight_read32(struct coresight_device *csdev, u32 offset) +{ + return csdev_access_read32(&csdev->access, offset); +} + +void coresight_relaxed_write32(struct coresight_device *csdev, + u32 val, + u32 offset) +{ + + csdev_access_relaxed_write32(&csdev->access, val, offset); +} + + +void coresight_write32(struct coresight_device *csdev, u32 val, u32 offset) +{ + csdev_access_write32(&csdev->access, val, offset); +} + +u64 coresight_relaxed_read64(struct coresight_device *csdev, u32 offset) +{ + return csdev_access_relaxed_read64(&csdev->access, offset); +} + +u64 coresight_read64(struct coresight_device *csdev, u32 offset) +{ + return csdev_access_read64(&csdev->access, offset); +} + +void coresight_relaxed_write64(struct coresight_device *csdev, + u64 val, + u32 offset) +{ + + csdev_access_relaxed_write64(&csdev->access, val, offset); +} + + +void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset) +{ + csdev_access_write64(&csdev->access, val, offset); +} + /* * coresight_release_platform_data: Release references to the devices connected * to the output port of this device. @@ -1451,6 +1499,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) csdev->type = desc->type; csdev->subtype = desc->subtype; csdev->ops = desc->ops; + csdev->access = desc->access; csdev->orphan = false;
csdev->dev.type = &coresight_dev_type[desc->type]; diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 58fffdecdbfd..1377240275d8 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -7,6 +7,7 @@ #define _LINUX_CORESIGHT_H
#include <linux/device.h> +#include <linux/io.h> #include <linux/perf_event.h> #include <linux/sched.h>
@@ -114,6 +115,38 @@ struct coresight_platform_data { struct coresight_connection *conns; };
+/** + * struct csdev_access - Abstraction of a CoreSight device access. + * + * @io_mem : True if the device has memory mapped I/O + * @base : When io_mem == true, base address of the component + * @read : Read from the given "offset" of the given instance. + * @write : Write "val" to the given "offset". + */ +struct csdev_access { + bool io_mem; + union { + void __iomem *base; + struct { + u64 (*read)(struct csdev_access *csa, + u32 offset, + bool relaxed, + bool _64bit); + void (*write)(struct csdev_access *csa, + u64 val, + u32 offset, + bool relaxed, + bool _64bit); + }; + }; +}; + +#define CSDEV_ACCESS_IOMEM(addr) \ + (struct csdev_access) { \ + .io_mem = true, \ + .base = addr, \ + } + /** * struct coresight_desc - description of a component required from drivers * @type: as defined by @coresight_dev_type. @@ -125,6 +158,7 @@ struct coresight_platform_data { * @groups: operations specific to this component. These will end up * in the component's sysfs sub-directory. * @name: name for the coresight device, also shown under sysfs. + * @access: Describe access to the device */ struct coresight_desc { enum coresight_dev_type type; @@ -134,6 +168,7 @@ struct coresight_desc { struct device *dev; const struct attribute_group **groups; const char *name; + struct csdev_access access; };
/** @@ -186,6 +221,7 @@ struct coresight_sysfs_link { * @def_sink: cached reference to default sink found for this device. * @ect_dev: Associated cross trigger device. Not part of the trace data * path or connections. + * @access: Device i/o access abstraction for this device. * @nr_links: number of sysfs links created to other components from this * device. These will appear in the "connections" group. * @has_conns_grp: Have added a "connections" group for sysfs links. @@ -205,6 +241,7 @@ struct coresight_device { struct coresight_device *def_sink; /* cross trigger handling */ struct coresight_device *ect_dev; + struct csdev_access access; /* sysfs links between components */ int nr_links; bool has_conns_grp; @@ -324,6 +361,107 @@ struct coresight_ops { const struct coresight_ops_ect *ect_ops; };
+static inline u32 csdev_access_relaxed_read32(struct csdev_access *csa, + u32 offset) +{ + if (likely(csa->io_mem)) + return readl_relaxed(csa->base + offset); + + return csa->read(csa, offset, true, false); +} + +static inline u32 csdev_access_read32(struct csdev_access *csa, u32 offset) +{ + if (likely(csa->io_mem)) + return readl(csa->base + offset); + + return csa->read(csa, offset, false, false); +} + +static inline void csdev_access_relaxed_write32(struct csdev_access *csa, + u32 val, + u32 offset) +{ + if (likely(csa->io_mem)) + writel_relaxed(val, csa->base + offset); + else + csa->write(csa, val, offset, true, false); +} + +static inline void csdev_access_write32(struct csdev_access *csa, u32 val, u32 offset) +{ + if (likely(csa->io_mem)) + writel(val, csa->base + offset); + else + csa->write(csa, val, offset, false, false); +} + +#ifdef CONFIG_64BIT + +static inline u64 csdev_access_relaxed_read64(struct csdev_access *csa, + u32 offset) +{ + if (likely(csa->io_mem)) + return readq_relaxed(csa->base + offset); + + return csa->read(csa, offset, true, true); +} + +static inline u64 csdev_access_read64(struct csdev_access *csa, u32 offset) +{ + if (likely(csa->io_mem)) + return readq(csa->base + offset); + + return csa->read(csa, offset, false, true); +} + +static inline void csdev_access_relaxed_write64(struct csdev_access *csa, + u64 val, + u32 offset) +{ + if (likely(csa->io_mem)) + writeq_relaxed(val, csa->base + offset); + else + csa->write(csa, val, offset, true, true); +} + +static inline void csdev_access_write64(struct csdev_access *csa, u64 val, u32 offset) +{ + if (likely(csa->io_mem)) + writeq(val, csa->base + offset); + else + csa->write(csa, val, offset, false, true); +} + +#else + +static inline u64 csdev_access_relaxed_read64(struct csdev_access *csa, + u32 offset) +{ + WARN_ON(1); + return 0; +} + +static inline u64 csdev_access_read64(struct csdev_access *csa, u32 offset) +{ + WARN_ON(1); + return 0; +} + +static inline void csdev_access_relaxed_write64(struct csdev_access *csa, + u64 val, + u32 offset) +{ + WARN_ON(1); +} + +static inline void csdev_access_write64(struct csdev_access *csa, u64 val, u32 offset) +{ + WARN_ON(1); +} +#endif + + #ifdef CONFIG_CORESIGHT extern struct coresight_device * coresight_register(struct coresight_desc *desc); @@ -342,6 +480,20 @@ extern char *coresight_alloc_device_name(struct coresight_dev_list *devs, struct device *dev);
extern bool coresight_loses_context_with_cpu(struct device *dev); + +u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset); +u32 coresight_read32(struct coresight_device *csdev, u32 offset); +void coresight_write32(struct coresight_device *csdev, u32 val, u32 offset); +void coresight_relaxed_write32(struct coresight_device *csdev, + u32 val, + u32 offset); +u64 coresight_relaxed_read64(struct coresight_device *csdev, u32 offset); +u64 coresight_read64(struct coresight_device *csdev, u32 offset); +void coresight_relaxed_write64(struct coresight_device *csdev, + u64 val, u32 offset); +void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset); + + #else static inline struct coresight_device * coresight_register(struct coresight_desc *desc) { return NULL; } @@ -368,6 +520,51 @@ static inline bool coresight_loses_context_with_cpu(struct device *dev) { return false; } + +static inline u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset) +{ + WARN_ON_ONCE(1); + return 0; +} + +static inline u32 coresight_read32(struct coresight_device *csdev, u32 offset) +{ + WARN_ON_ONCE(1); + return 0; +} + +static inline void coresight_write32(struct coresight_device *csdev, u32 val, u32 offset) +{ +} + +static inline void coresight_relaxed_write32(struct coresight_device *csdev, + u32 val, u32 offset); +{ +} + +static inline u64 coresight_relaxed_read64(struct coresight_device *csdev, + u32 offset) +{ + WARN_ON_ONCE(1); + return 0; +} + +static inline u64 coresight_read64(struct coresight_device *csdev, u32 offset) +{ + WARN_ON_ONCE(1); + return 0; +} + +static inline void coresight_relaxed_write64(struct coresight_device *csdev, + u64 val, + u32 offset) +{ +} + +static inline void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset) +{ +} + #endif
extern int coresight_get_cpu(struct device *dev);
Reviewed-by: Mike Leach mike.leach@linaro.org
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
We are about to introduce support for sysreg access to ETMv4.4+ component. Since there are generic routines that access the registers (e.g, CS_LOCK/UNLOCK , claim/disclaim operations, timeout) and in order to preserve the logic of these operations at a single place we introduce an abstraction layer for the accesses to a given device.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-catu.c | 1 + drivers/hwtracing/coresight/coresight-cti.c | 1 + drivers/hwtracing/coresight/coresight-etb10.c | 1 + drivers/hwtracing/coresight/coresight-etm3x.c | 1 + drivers/hwtracing/coresight/coresight-etm4x.c | 1 + .../hwtracing/coresight/coresight-funnel.c | 1 + .../coresight/coresight-replicator.c | 1 + drivers/hwtracing/coresight/coresight-stm.c | 1 + drivers/hwtracing/coresight/coresight-tmc.c | 1 + drivers/hwtracing/coresight/coresight-tpiu.c | 1 + drivers/hwtracing/coresight/coresight.c | 49 +++++ include/linux/coresight.h | 197 ++++++++++++++++++ 12 files changed, 256 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 1801804a7762..90da0b842717 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -551,6 +551,7 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id) dev->platform_data = pdata;
drvdata->base = base;
catu_desc.access = CSDEV_ACCESS_IOMEM(base); catu_desc.pdata = pdata; catu_desc.dev = dev; catu_desc.groups = catu_groups;
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index 47f3c9abae30..e13e24e4a858 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -849,6 +849,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base;
cti_desc.access = CSDEV_ACCESS_IOMEM(base); dev_set_drvdata(dev, drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 03e3f2590191..42fe174a68f0 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -755,6 +755,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base); spin_lock_init(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index bf22dcfd3327..e3724d8adecb 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -805,6 +805,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base); spin_lock_init(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 00c9f0bb8b1a..466e6f304751 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1488,6 +1488,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base); spin_lock_init(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 900690a9f7f0..e8e233cbc130 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -242,6 +242,7 @@ static int funnel_probe(struct device *dev, struct resource *res) } drvdata->base = base; desc.groups = coresight_funnel_groups;
desc.access = CSDEV_ACCESS_IOMEM(base); } dev_set_drvdata(dev, drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 78acf29c49ca..8ba9cbe1d108 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -254,6 +254,7 @@ static int replicator_probe(struct device *dev, struct resource *res) } drvdata->base = base; desc.groups = replicator_groups;
desc.access = CSDEV_ACCESS_IOMEM(base); } if (fwnode_property_present(dev_fwnode(dev),
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 2ba819a47cf6..fbf86f31f2ab 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -884,6 +884,7 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id) if (IS_ERR(base)) return PTR_ERR(base); drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base); ret = stm_get_stimulus_area(dev, &ch_res); if (ret)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 7040d583bed9..5711e55c310c 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -458,6 +458,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) }
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base); spin_lock_init(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index f8583e4032a6..4eb3f50618b6 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -149,6 +149,7 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base); /* Disable tpiu to support older devices */ tpiu_disable_hw(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index e9c90f2de34a..38e9c03ab754 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1387,6 +1387,54 @@ static int __init coresight_init(void) } postcore_initcall(coresight_init);
+u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset) +{
return csdev_access_relaxed_read32(&csdev->access, offset);
+}
+u32 coresight_read32(struct coresight_device *csdev, u32 offset) +{
return csdev_access_read32(&csdev->access, offset);
+}
+void coresight_relaxed_write32(struct coresight_device *csdev,
u32 val,
u32 offset)
+{
csdev_access_relaxed_write32(&csdev->access, val, offset);
+}
+void coresight_write32(struct coresight_device *csdev, u32 val, u32 offset) +{
csdev_access_write32(&csdev->access, val, offset);
+}
+u64 coresight_relaxed_read64(struct coresight_device *csdev, u32 offset) +{
return csdev_access_relaxed_read64(&csdev->access, offset);
+}
+u64 coresight_read64(struct coresight_device *csdev, u32 offset) +{
return csdev_access_read64(&csdev->access, offset);
+}
+void coresight_relaxed_write64(struct coresight_device *csdev,
u64 val,
u32 offset)
+{
csdev_access_relaxed_write64(&csdev->access, val, offset);
+}
+void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset) +{
csdev_access_write64(&csdev->access, val, offset);
+}
/*
- coresight_release_platform_data: Release references to the devices connected
- to the output port of this device.
@@ -1451,6 +1499,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) csdev->type = desc->type; csdev->subtype = desc->subtype; csdev->ops = desc->ops;
csdev->access = desc->access; csdev->orphan = false; csdev->dev.type = &coresight_dev_type[desc->type];
diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 58fffdecdbfd..1377240275d8 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -7,6 +7,7 @@ #define _LINUX_CORESIGHT_H
#include <linux/device.h> +#include <linux/io.h> #include <linux/perf_event.h> #include <linux/sched.h>
@@ -114,6 +115,38 @@ struct coresight_platform_data { struct coresight_connection *conns; };
+/**
- struct csdev_access - Abstraction of a CoreSight device access.
- @io_mem : True if the device has memory mapped I/O
- @base : When io_mem == true, base address of the component
- @read : Read from the given "offset" of the given instance.
- @write : Write "val" to the given "offset".
- */
+struct csdev_access {
bool io_mem;
union {
void __iomem *base;
struct {
u64 (*read)(struct csdev_access *csa,
u32 offset,
bool relaxed,
bool _64bit);
void (*write)(struct csdev_access *csa,
u64 val,
u32 offset,
bool relaxed,
bool _64bit);
};
};
+};
+#define CSDEV_ACCESS_IOMEM(addr) \
(struct csdev_access) { \
.io_mem = true, \
.base = addr, \
}
/**
- struct coresight_desc - description of a component required from drivers
- @type: as defined by @coresight_dev_type.
@@ -125,6 +158,7 @@ struct coresight_platform_data {
- @groups: operations specific to this component. These will end up
in the component's sysfs sub-directory.
- @name: name for the coresight device, also shown under sysfs.
*/
- @access: Describe access to the device
struct coresight_desc { enum coresight_dev_type type; @@ -134,6 +168,7 @@ struct coresight_desc { struct device *dev; const struct attribute_group **groups; const char *name;
struct csdev_access access;
};
/** @@ -186,6 +221,7 @@ struct coresight_sysfs_link {
- @def_sink: cached reference to default sink found for this device.
- @ect_dev: Associated cross trigger device. Not part of the trace data
path or connections.
- @access: Device i/o access abstraction for this device.
- @nr_links: number of sysfs links created to other components from this
device. These will appear in the "connections" group.
- @has_conns_grp: Have added a "connections" group for sysfs links.
@@ -205,6 +241,7 @@ struct coresight_device { struct coresight_device *def_sink; /* cross trigger handling */ struct coresight_device *ect_dev;
struct csdev_access access; /* sysfs links between components */ int nr_links; bool has_conns_grp;
@@ -324,6 +361,107 @@ struct coresight_ops { const struct coresight_ops_ect *ect_ops; };
+static inline u32 csdev_access_relaxed_read32(struct csdev_access *csa,
u32 offset)
+{
if (likely(csa->io_mem))
return readl_relaxed(csa->base + offset);
return csa->read(csa, offset, true, false);
+}
+static inline u32 csdev_access_read32(struct csdev_access *csa, u32 offset) +{
if (likely(csa->io_mem))
return readl(csa->base + offset);
return csa->read(csa, offset, false, false);
+}
+static inline void csdev_access_relaxed_write32(struct csdev_access *csa,
u32 val,
u32 offset)
+{
if (likely(csa->io_mem))
writel_relaxed(val, csa->base + offset);
else
csa->write(csa, val, offset, true, false);
+}
+static inline void csdev_access_write32(struct csdev_access *csa, u32 val, u32 offset) +{
if (likely(csa->io_mem))
writel(val, csa->base + offset);
else
csa->write(csa, val, offset, false, false);
+}
+#ifdef CONFIG_64BIT
+static inline u64 csdev_access_relaxed_read64(struct csdev_access *csa,
u32 offset)
+{
if (likely(csa->io_mem))
return readq_relaxed(csa->base + offset);
return csa->read(csa, offset, true, true);
+}
+static inline u64 csdev_access_read64(struct csdev_access *csa, u32 offset) +{
if (likely(csa->io_mem))
return readq(csa->base + offset);
return csa->read(csa, offset, false, true);
+}
+static inline void csdev_access_relaxed_write64(struct csdev_access *csa,
u64 val,
u32 offset)
+{
if (likely(csa->io_mem))
writeq_relaxed(val, csa->base + offset);
else
csa->write(csa, val, offset, true, true);
+}
+static inline void csdev_access_write64(struct csdev_access *csa, u64 val, u32 offset) +{
if (likely(csa->io_mem))
writeq(val, csa->base + offset);
else
csa->write(csa, val, offset, false, true);
+}
+#else
+static inline u64 csdev_access_relaxed_read64(struct csdev_access *csa,
u32 offset)
+{
WARN_ON(1);
return 0;
+}
+static inline u64 csdev_access_read64(struct csdev_access *csa, u32 offset) +{
WARN_ON(1);
return 0;
+}
+static inline void csdev_access_relaxed_write64(struct csdev_access *csa,
u64 val,
u32 offset)
+{
WARN_ON(1);
+}
+static inline void csdev_access_write64(struct csdev_access *csa, u64 val, u32 offset) +{
WARN_ON(1);
+} +#endif
#ifdef CONFIG_CORESIGHT extern struct coresight_device * coresight_register(struct coresight_desc *desc); @@ -342,6 +480,20 @@ extern char *coresight_alloc_device_name(struct coresight_dev_list *devs, struct device *dev);
extern bool coresight_loses_context_with_cpu(struct device *dev);
+u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset); +u32 coresight_read32(struct coresight_device *csdev, u32 offset); +void coresight_write32(struct coresight_device *csdev, u32 val, u32 offset); +void coresight_relaxed_write32(struct coresight_device *csdev,
u32 val,
u32 offset);
+u64 coresight_relaxed_read64(struct coresight_device *csdev, u32 offset); +u64 coresight_read64(struct coresight_device *csdev, u32 offset); +void coresight_relaxed_write64(struct coresight_device *csdev,
u64 val, u32 offset);
+void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset);
#else static inline struct coresight_device * coresight_register(struct coresight_desc *desc) { return NULL; } @@ -368,6 +520,51 @@ static inline bool coresight_loses_context_with_cpu(struct device *dev) { return false; }
+static inline u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset) +{
WARN_ON_ONCE(1);
return 0;
+}
+static inline u32 coresight_read32(struct coresight_device *csdev, u32 offset) +{
WARN_ON_ONCE(1);
return 0;
+}
+static inline void coresight_write32(struct coresight_device *csdev, u32 val, u32 offset) +{ +}
+static inline void coresight_relaxed_write32(struct coresight_device *csdev,
u32 val, u32 offset);
+{ +}
+static inline u64 coresight_relaxed_read64(struct coresight_device *csdev,
u32 offset)
+{
WARN_ON_ONCE(1);
return 0;
+}
+static inline u64 coresight_read64(struct coresight_device *csdev, u32 offset) +{
WARN_ON_ONCE(1);
return 0;
+}
+static inline void coresight_relaxed_write64(struct coresight_device *csdev,
u64 val,
u32 offset)
+{ +}
+static inline void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset) +{ +}
#endif
extern int coresight_get_cpu(struct device *dev);
2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Prepare the TPIU driver to make use of the CoreSight device access abstraction layer. The driver touches the device even before the coresight device is registered. Thus we could be accessing the devices without a csdev. As we are about to use the abstraction layer for accessing the device, pass in the access directly to avoid having to deal with the un-initialised csdev.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-tpiu.c | 30 +++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 4eb3f50618b6..cc7d7ed474f5 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -60,49 +60,45 @@ struct tpiu_drvdata { struct coresight_device *csdev; };
-static void tpiu_enable_hw(struct tpiu_drvdata *drvdata) +static void tpiu_enable_hw(struct csdev_access *csa) { - CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa->base);
/* TODO: fill this up */
- CS_LOCK(drvdata->base); + CS_LOCK(csa->base); }
static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused) { - struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - - tpiu_enable_hw(drvdata); + tpiu_enable_hw(&csdev->access); atomic_inc(csdev->refcnt); dev_dbg(&csdev->dev, "TPIU enabled\n"); return 0; }
-static void tpiu_disable_hw(struct tpiu_drvdata *drvdata) +static void tpiu_disable_hw(struct csdev_access *csa) { - CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa->base);
/* Clear formatter and stop on flush */ - writel_relaxed(FFCR_STOP_FI, drvdata->base + TPIU_FFCR); + csdev_access_relaxed_write32(csa, FFCR_STOP_FI, TPIU_FFCR); /* Generate manual flush */ - writel_relaxed(FFCR_STOP_FI | FFCR_FON_MAN, drvdata->base + TPIU_FFCR); + csdev_access_relaxed_write32(csa, FFCR_STOP_FI | FFCR_FON_MAN, TPIU_FFCR); /* Wait for flush to complete */ - coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0); + coresight_timeout(csa->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0); /* Wait for formatter to stop */ - coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1); + coresight_timeout(csa->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
- CS_LOCK(drvdata->base); + CS_LOCK(csa->base); }
static int tpiu_disable(struct coresight_device *csdev) { - struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - if (atomic_dec_return(csdev->refcnt)) return -EBUSY;
- tpiu_disable_hw(drvdata); + tpiu_disable_hw(&csdev->access);
dev_dbg(&csdev->dev, "TPIU disabled\n"); return 0; @@ -152,7 +148,7 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) desc.access = CSDEV_ACCESS_IOMEM(base);
/* Disable tpiu to support older devices */ - tpiu_disable_hw(drvdata); + tpiu_disable_hw(&desc.access);
pdata = coresight_get_platform_data(dev); if (IS_ERR(pdata))
Reviewed-by: Mike Leach mike.leach@linaro.org
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Prepare the TPIU driver to make use of the CoreSight device access abstraction layer. The driver touches the device even before the coresight device is registered. Thus we could be accessing the devices without a csdev. As we are about to use the abstraction layer for accessing the device, pass in the access directly to avoid having to deal with the un-initialised csdev.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-tpiu.c | 30 +++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 4eb3f50618b6..cc7d7ed474f5 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -60,49 +60,45 @@ struct tpiu_drvdata { struct coresight_device *csdev; };
-static void tpiu_enable_hw(struct tpiu_drvdata *drvdata) +static void tpiu_enable_hw(struct csdev_access *csa) {
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa->base); /* TODO: fill this up */
CS_LOCK(drvdata->base);
CS_LOCK(csa->base);
}
static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused) {
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
tpiu_enable_hw(drvdata);
tpiu_enable_hw(&csdev->access); atomic_inc(csdev->refcnt); dev_dbg(&csdev->dev, "TPIU enabled\n"); return 0;
}
-static void tpiu_disable_hw(struct tpiu_drvdata *drvdata) +static void tpiu_disable_hw(struct csdev_access *csa) {
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa->base); /* Clear formatter and stop on flush */
writel_relaxed(FFCR_STOP_FI, drvdata->base + TPIU_FFCR);
csdev_access_relaxed_write32(csa, FFCR_STOP_FI, TPIU_FFCR); /* Generate manual flush */
writel_relaxed(FFCR_STOP_FI | FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
csdev_access_relaxed_write32(csa, FFCR_STOP_FI | FFCR_FON_MAN, TPIU_FFCR); /* Wait for flush to complete */
coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
coresight_timeout(csa->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0); /* Wait for formatter to stop */
coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
coresight_timeout(csa->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
CS_LOCK(drvdata->base);
CS_LOCK(csa->base);
}
static int tpiu_disable(struct coresight_device *csdev) {
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
if (atomic_dec_return(csdev->refcnt)) return -EBUSY;
tpiu_disable_hw(drvdata);
tpiu_disable_hw(&csdev->access); dev_dbg(&csdev->dev, "TPIU disabled\n"); return 0;
@@ -152,7 +148,7 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) desc.access = CSDEV_ACCESS_IOMEM(base);
/* Disable tpiu to support older devices */
tpiu_disable_hw(drvdata);
tpiu_disable_hw(&desc.access); pdata = coresight_get_platform_data(dev); if (IS_ERR(pdata))
-- 2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Convert the generic routines to use the new access abstraction layer gradually, starting with coresigth_timeout.
Cc: Mike Leach mike.leach@linaro.org Reviewed-by: Mathieu Poirier mathieu.poirier@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-catu.c | 5 ++-- drivers/hwtracing/coresight/coresight-etb10.c | 5 ++-- drivers/hwtracing/coresight/coresight-etm4x.c | 30 ++++++++++++------- drivers/hwtracing/coresight/coresight-stm.c | 3 +- drivers/hwtracing/coresight/coresight-tmc.c | 15 ++++++---- drivers/hwtracing/coresight/coresight-tpiu.c | 4 +-- drivers/hwtracing/coresight/coresight.c | 15 ++++++---- include/linux/coresight.h | 17 ++++++++--- 8 files changed, 61 insertions(+), 33 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 90da0b842717..15e63e52ff23 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -401,8 +401,9 @@ static const struct attribute_group *catu_groups[] = {
static inline int catu_wait_for_ready(struct catu_drvdata *drvdata) { - return coresight_timeout(drvdata->base, - CATU_STATUS, CATU_STATUS_READY, 1); + struct csdev_access *csa = &drvdata->csdev->access; + + return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1); }
static int catu_enable_hw(struct catu_drvdata *drvdata, void *data) diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 42fe174a68f0..2786d02dd23b 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -251,6 +251,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) { u32 ffcr; struct device *dev = &drvdata->csdev->dev; + struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
@@ -262,7 +263,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) ffcr |= ETB_FFCR_FON_MAN; writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
- if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) { + if (coresight_timeout(csa, ETB_FFCR, ETB_FFCR_BIT, 0)) { dev_err(dev, "timeout while waiting for completion of Manual Flush\n"); } @@ -270,7 +271,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) /* disable trace capture */ writel_relaxed(0x0, drvdata->base + ETB_CTL_REG);
- if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) { + if (coresight_timeout(csa, ETB_FFSR, ETB_FFSR_BIT, 1)) { dev_err(dev, "timeout while waiting for Formatter to Stop\n"); } diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 466e6f304751..973fb0fd4826 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -107,7 +107,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) { int i, rc; struct etmv4_config *config = &drvdata->config; - struct device *etm_dev = &drvdata->csdev->dev; + struct coresight_device *csdev = drvdata->csdev; + struct device *etm_dev = &csdev->dev; + struct csdev_access *csa = &csdev->access;
CS_UNLOCK(drvdata->base);
@@ -121,7 +123,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) writel_relaxed(0, drvdata->base + TRCPRGCTLR);
/* wait for TRCSTATR.IDLE to go up */ - if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) dev_err(etm_dev, "timeout while waiting for Idle Trace Status\n");
@@ -208,7 +210,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) writel_relaxed(1, drvdata->base + TRCPRGCTLR);
/* wait for TRCSTATR.IDLE to go back down to '0' */ - if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) dev_err(etm_dev, "timeout while waiting for Idle Trace Status\n");
@@ -472,7 +474,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; + struct coresight_device *csdev = drvdata->csdev; + struct device *etm_dev = &csdev->dev; + struct csdev_access *csa = &csdev->access; int i;
CS_UNLOCK(drvdata->base); @@ -499,8 +503,7 @@ static void etm4_disable_hw(void *info) writel_relaxed(control, drvdata->base + TRCPRGCTLR);
/* wait for TRCSTATR.PMSTABLE to go to '1' */ - if (coresight_timeout(drvdata->base, TRCSTATR, - TRCSTATR_PMSTABLE_BIT, 1)) + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) dev_err(etm_dev, "timeout while waiting for PM stable Trace Status\n");
@@ -1145,7 +1148,15 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) { int i, ret = 0; struct etmv4_save_state *state; - struct device *etm_dev = &drvdata->csdev->dev; + struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa; + struct device *etm_dev; + + if (WARN_ON(!csdev)) + return -ENODEV; + + etm_dev = &csdev->dev; + csa = &csdev->access;
/* * As recommended by 3.4.1 ("The procedure when powering down the PE") @@ -1160,8 +1171,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) etm4_os_lock(drvdata);
/* wait for TRCSTATR.PMSTABLE to go up */ - if (coresight_timeout(drvdata->base, TRCSTATR, - TRCSTATR_PMSTABLE_BIT, 1)) { + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) { dev_err(etm_dev, "timeout while waiting for PM Stable Status\n"); etm4_os_unlock(drvdata); @@ -1244,7 +1254,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) state->trcpdcr = readl(drvdata->base + TRCPDCR);
/* wait for TRCSTATR.IDLE to go up */ - if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) { + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) { dev_err(etm_dev, "timeout while waiting for Idle Trace Status\n"); etm4_os_unlock(drvdata); diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index fbf86f31f2ab..9667c5c8f433 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -258,6 +258,7 @@ static void stm_disable(struct coresight_device *csdev, struct perf_event *event) { struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + struct csdev_access *csa = &csdev->access;
/* * For as long as the tracer isn't disabled another entity can't @@ -270,7 +271,7 @@ static void stm_disable(struct coresight_device *csdev, spin_unlock(&drvdata->spinlock);
/* Wait until the engine has completely stopped */ - coresight_timeout(drvdata->base, STMTCSR, STMTCSR_BUSY_BIT, 0); + coresight_timeout(csa, STMTCSR, STMTCSR_BUSY_BIT, 0);
pm_runtime_put(csdev->dev.parent);
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 5711e55c310c..cc9d97f9eb5b 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -33,16 +33,20 @@ DEFINE_CORESIGHT_DEVLIST(etr_devs, "tmc_etr");
void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata) { + struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &csdev->access; + /* Ensure formatter, unformatter and hardware fifo are empty */ - if (coresight_timeout(drvdata->base, - TMC_STS, TMC_STS_TMCREADY_BIT, 1)) { - dev_err(&drvdata->csdev->dev, + if (coresight_timeout(csa, TMC_STS, TMC_STS_TMCREADY_BIT, 1)) { + dev_err(&csdev->dev, "timeout while waiting for TMC to be Ready\n"); } }
void tmc_flush_and_stop(struct tmc_drvdata *drvdata) { + struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &csdev->access; u32 ffcr;
ffcr = readl_relaxed(drvdata->base + TMC_FFCR); @@ -51,9 +55,8 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata) ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT); writel_relaxed(ffcr, drvdata->base + TMC_FFCR); /* Ensure flush completes */ - if (coresight_timeout(drvdata->base, - TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) { - dev_err(&drvdata->csdev->dev, + if (coresight_timeout(csa, TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) { + dev_err(&csdev->dev, "timeout while waiting for completion of Manual Flush\n"); }
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index cc7d7ed474f5..7dd8300cf6be 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -86,9 +86,9 @@ static void tpiu_disable_hw(struct csdev_access *csa) /* Generate manual flush */ csdev_access_relaxed_write32(csa, FFCR_STOP_FI | FFCR_FON_MAN, TPIU_FFCR); /* Wait for flush to complete */ - coresight_timeout(csa->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0); + coresight_timeout(csa, TPIU_FFCR, FFCR_FON_MAN_BIT, 0); /* Wait for formatter to stop */ - coresight_timeout(csa->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1); + coresight_timeout(csa, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
CS_LOCK(csa->base); } diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 38e9c03ab754..21e7615fcbc8 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1338,23 +1338,26 @@ static void coresight_remove_conns(struct coresight_device *csdev) }
/** - * coresight_timeout - loop until a bit has changed to a specific state. - * @addr: base address of the area of interest. - * @offset: address of a register, starting from @addr. + * coresight_timeout - loop until a bit has changed to a specific register + * state. + * @csa: coresight device access for the device + * @offset: Offset of the register from the base of the device. * @position: the position of the bit of interest. * @value: the value the bit should have. * * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if * TIMEOUT_US has elapsed, which ever happens first. */ - -int coresight_timeout(void __iomem *addr, u32 offset, int position, int value) +int coresight_timeout(struct csdev_access *csa, + u32 offset, + int position, + int value) { int i; u32 val;
for (i = TIMEOUT_US; i > 0; i--) { - val = __raw_readl(addr + offset); + val = csdev_access_read32(csa, offset); /* waiting on the bit to go from 0 to 1 */ if (value) { if (val & BIT(position)) diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 1377240275d8..55a9c3276a28 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -468,8 +468,10 @@ coresight_register(struct coresight_desc *desc); extern void coresight_unregister(struct coresight_device *csdev); extern int coresight_enable(struct coresight_device *csdev); extern void coresight_disable(struct coresight_device *csdev); -extern int coresight_timeout(void __iomem *addr, u32 offset, - int position, int value); +extern int coresight_timeout(struct csdev_access *csa, + u32 offset, + int position, + int value);
extern int coresight_claim_device(void __iomem *base); extern int coresight_claim_device_unlocked(void __iomem *base); @@ -501,8 +503,15 @@ static inline void coresight_unregister(struct coresight_device *csdev) {} static inline int coresight_enable(struct coresight_device *csdev) { return -ENOSYS; } static inline void coresight_disable(struct coresight_device *csdev) {} -static inline int coresight_timeout(void __iomem *addr, u32 offset, - int position, int value) { return 1; } + +static inline int coresight_timeout(struct csdev_access *csa, + u32 offset, + int position, + int value) +{ + return 1; +} + static inline int coresight_claim_device_unlocked(void __iomem *base) { return -EINVAL;
Reviewed-by: Mike Leach mike.leach@linaro.org
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Convert the generic routines to use the new access abstraction layer gradually, starting with coresigth_timeout.
Cc: Mike Leach mike.leach@linaro.org Reviewed-by: Mathieu Poirier mathieu.poirier@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-catu.c | 5 ++-- drivers/hwtracing/coresight/coresight-etb10.c | 5 ++-- drivers/hwtracing/coresight/coresight-etm4x.c | 30 ++++++++++++------- drivers/hwtracing/coresight/coresight-stm.c | 3 +- drivers/hwtracing/coresight/coresight-tmc.c | 15 ++++++---- drivers/hwtracing/coresight/coresight-tpiu.c | 4 +-- drivers/hwtracing/coresight/coresight.c | 15 ++++++---- include/linux/coresight.h | 17 ++++++++--- 8 files changed, 61 insertions(+), 33 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 90da0b842717..15e63e52ff23 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -401,8 +401,9 @@ static const struct attribute_group *catu_groups[] = {
static inline int catu_wait_for_ready(struct catu_drvdata *drvdata) {
return coresight_timeout(drvdata->base,
CATU_STATUS, CATU_STATUS_READY, 1);
struct csdev_access *csa = &drvdata->csdev->access;
return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
}
static int catu_enable_hw(struct catu_drvdata *drvdata, void *data) diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 42fe174a68f0..2786d02dd23b 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -251,6 +251,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) { u32 ffcr; struct device *dev = &drvdata->csdev->dev;
struct csdev_access *csa = &drvdata->csdev->access; CS_UNLOCK(drvdata->base);
@@ -262,7 +263,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) ffcr |= ETB_FFCR_FON_MAN; writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
if (coresight_timeout(csa, ETB_FFCR, ETB_FFCR_BIT, 0)) { dev_err(dev, "timeout while waiting for completion of Manual Flush\n"); }
@@ -270,7 +271,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) /* disable trace capture */ writel_relaxed(0x0, drvdata->base + ETB_CTL_REG);
if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
if (coresight_timeout(csa, ETB_FFSR, ETB_FFSR_BIT, 1)) { dev_err(dev, "timeout while waiting for Formatter to Stop\n"); }
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 466e6f304751..973fb0fd4826 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -107,7 +107,9 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) { int i, rc; struct etmv4_config *config = &drvdata->config;
struct device *etm_dev = &drvdata->csdev->dev;
struct coresight_device *csdev = drvdata->csdev;
struct device *etm_dev = &csdev->dev;
struct csdev_access *csa = &csdev->access; CS_UNLOCK(drvdata->base);
@@ -121,7 +123,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) writel_relaxed(0, drvdata->base + TRCPRGCTLR);
/* wait for TRCSTATR.IDLE to go up */
if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1))
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) dev_err(etm_dev, "timeout while waiting for Idle Trace Status\n");
@@ -208,7 +210,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) writel_relaxed(1, drvdata->base + TRCPRGCTLR);
/* wait for TRCSTATR.IDLE to go back down to '0' */
if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) dev_err(etm_dev, "timeout while waiting for Idle Trace Status\n");
@@ -472,7 +474,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;
struct coresight_device *csdev = drvdata->csdev;
struct device *etm_dev = &csdev->dev;
struct csdev_access *csa = &csdev->access; int i; CS_UNLOCK(drvdata->base);
@@ -499,8 +503,7 @@ static void etm4_disable_hw(void *info) writel_relaxed(control, drvdata->base + TRCPRGCTLR);
/* wait for TRCSTATR.PMSTABLE to go to '1' */
if (coresight_timeout(drvdata->base, TRCSTATR,
TRCSTATR_PMSTABLE_BIT, 1))
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) dev_err(etm_dev, "timeout while waiting for PM stable Trace Status\n");
@@ -1145,7 +1148,15 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) { int i, ret = 0; struct etmv4_save_state *state;
struct device *etm_dev = &drvdata->csdev->dev;
struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa;
struct device *etm_dev;
if (WARN_ON(!csdev))
return -ENODEV;
etm_dev = &csdev->dev;
csa = &csdev->access; /* * As recommended by 3.4.1 ("The procedure when powering down the PE")
@@ -1160,8 +1171,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) etm4_os_lock(drvdata);
/* wait for TRCSTATR.PMSTABLE to go up */
if (coresight_timeout(drvdata->base, TRCSTATR,
TRCSTATR_PMSTABLE_BIT, 1)) {
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) { dev_err(etm_dev, "timeout while waiting for PM Stable Status\n"); etm4_os_unlock(drvdata);
@@ -1244,7 +1254,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) state->trcpdcr = readl(drvdata->base + TRCPDCR);
/* wait for TRCSTATR.IDLE to go up */
if (coresight_timeout(drvdata->base, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) { dev_err(etm_dev, "timeout while waiting for Idle Trace Status\n"); etm4_os_unlock(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index fbf86f31f2ab..9667c5c8f433 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -258,6 +258,7 @@ static void stm_disable(struct coresight_device *csdev, struct perf_event *event) { struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct csdev_access *csa = &csdev->access; /* * For as long as the tracer isn't disabled another entity can't
@@ -270,7 +271,7 @@ static void stm_disable(struct coresight_device *csdev, spin_unlock(&drvdata->spinlock);
/* Wait until the engine has completely stopped */
coresight_timeout(drvdata->base, STMTCSR, STMTCSR_BUSY_BIT, 0);
coresight_timeout(csa, STMTCSR, STMTCSR_BUSY_BIT, 0); pm_runtime_put(csdev->dev.parent);
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 5711e55c310c..cc9d97f9eb5b 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -33,16 +33,20 @@ DEFINE_CORESIGHT_DEVLIST(etr_devs, "tmc_etr");
void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata) {
struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access;
/* Ensure formatter, unformatter and hardware fifo are empty */
if (coresight_timeout(drvdata->base,
TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
dev_err(&drvdata->csdev->dev,
if (coresight_timeout(csa, TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
dev_err(&csdev->dev, "timeout while waiting for TMC to be Ready\n"); }
}
void tmc_flush_and_stop(struct tmc_drvdata *drvdata) {
struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access; u32 ffcr; ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
@@ -51,9 +55,8 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata) ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT); writel_relaxed(ffcr, drvdata->base + TMC_FFCR); /* Ensure flush completes */
if (coresight_timeout(drvdata->base,
TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
dev_err(&drvdata->csdev->dev,
if (coresight_timeout(csa, TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
dev_err(&csdev->dev, "timeout while waiting for completion of Manual Flush\n"); }
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index cc7d7ed474f5..7dd8300cf6be 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -86,9 +86,9 @@ static void tpiu_disable_hw(struct csdev_access *csa) /* Generate manual flush */ csdev_access_relaxed_write32(csa, FFCR_STOP_FI | FFCR_FON_MAN, TPIU_FFCR); /* Wait for flush to complete */
coresight_timeout(csa->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
coresight_timeout(csa, TPIU_FFCR, FFCR_FON_MAN_BIT, 0); /* Wait for formatter to stop */
coresight_timeout(csa->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
coresight_timeout(csa, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1); CS_LOCK(csa->base);
} diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 38e9c03ab754..21e7615fcbc8 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1338,23 +1338,26 @@ static void coresight_remove_conns(struct coresight_device *csdev) }
/**
- coresight_timeout - loop until a bit has changed to a specific state.
- @addr: base address of the area of interest.
- @offset: address of a register, starting from @addr.
- coresight_timeout - loop until a bit has changed to a specific register
state.
- @csa: coresight device access for the device
*/
- @offset: Offset of the register from the base of the device.
- @position: the position of the bit of interest.
- @value: the value the bit should have.
- Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
- TIMEOUT_US has elapsed, which ever happens first.
-int coresight_timeout(void __iomem *addr, u32 offset, int position, int value) +int coresight_timeout(struct csdev_access *csa,
u32 offset,
int position,
int value)
{ int i; u32 val;
for (i = TIMEOUT_US; i > 0; i--) {
val = __raw_readl(addr + offset);
val = csdev_access_read32(csa, offset); /* waiting on the bit to go from 0 to 1 */ if (value) { if (val & BIT(position))
diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 1377240275d8..55a9c3276a28 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -468,8 +468,10 @@ coresight_register(struct coresight_desc *desc); extern void coresight_unregister(struct coresight_device *csdev); extern int coresight_enable(struct coresight_device *csdev); extern void coresight_disable(struct coresight_device *csdev); -extern int coresight_timeout(void __iomem *addr, u32 offset,
int position, int value);
+extern int coresight_timeout(struct csdev_access *csa,
u32 offset,
int position,
int value);
extern int coresight_claim_device(void __iomem *base); extern int coresight_claim_device_unlocked(void __iomem *base); @@ -501,8 +503,15 @@ static inline void coresight_unregister(struct coresight_device *csdev) {} static inline int coresight_enable(struct coresight_device *csdev) { return -ENOSYS; } static inline void coresight_disable(struct coresight_device *csdev) {} -static inline int coresight_timeout(void __iomem *addr, u32 offset,
int position, int value) { return 1; }
+static inline int coresight_timeout(struct csdev_access *csa,
u32 offset,
int position,
int value)
+{
return 1;
+}
static inline int coresight_claim_device_unlocked(void __iomem *base) { return -EINVAL; -- 2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Convert the generic CLAIM tag management APIs to use the device access layer abstraction.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-catu.c | 6 +- drivers/hwtracing/coresight/coresight-cti.c | 17 +++-- drivers/hwtracing/coresight/coresight-etb10.c | 4 +- drivers/hwtracing/coresight/coresight-etm3x.c | 8 ++- drivers/hwtracing/coresight/coresight-etm4x.c | 4 +- .../hwtracing/coresight/coresight-funnel.c | 6 +- .../coresight/coresight-replicator.c | 16 +++-- .../hwtracing/coresight/coresight-tmc-etf.c | 10 +-- .../hwtracing/coresight/coresight-tmc-etr.c | 4 +- drivers/hwtracing/coresight/coresight.c | 66 +++++++++++-------- include/linux/coresight.h | 16 ++--- 11 files changed, 95 insertions(+), 62 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 15e63e52ff23..df2f45457e2b 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -412,6 +412,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data) u32 control, mode; struct etr_buf *etr_buf = data; struct device *dev = &drvdata->csdev->dev; + struct coresight_device *csdev = drvdata->csdev;
if (catu_wait_for_ready(drvdata)) dev_warn(dev, "Timeout while waiting for READY\n"); @@ -422,7 +423,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data) return -EBUSY; }
- rc = coresight_claim_device_unlocked(drvdata->base); + rc = coresight_claim_device_unlocked(csdev); if (rc) return rc;
@@ -466,9 +467,10 @@ static int catu_disable_hw(struct catu_drvdata *drvdata) { int rc = 0; struct device *dev = &drvdata->csdev->dev; + struct coresight_device *csdev = drvdata->csdev;
catu_write_control(drvdata, 0); - coresight_disclaim_device_unlocked(drvdata->base); + coresight_disclaim_device_unlocked(csdev); if (catu_wait_for_ready(drvdata)) { dev_info(dev, "Timeout while waiting for READY\n"); rc = -EAGAIN; diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index e13e24e4a858..e07e15593dd8 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -102,7 +102,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) goto cti_state_unchanged;
/* claim the device */ - rc = coresight_claim_device(drvdata->base); + rc = coresight_claim_device(drvdata->csdev); if (rc) goto cti_err_not_enabled;
@@ -136,7 +136,7 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata) goto cti_hp_not_enabled;
/* try to claim the device */ - if (coresight_claim_device(drvdata->base)) + if (coresight_claim_device(drvdata->csdev)) goto cti_hp_not_enabled;
cti_write_all_hw_regs(drvdata); @@ -154,6 +154,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; struct device *dev = &drvdata->csdev->dev; + struct coresight_device *csdev = drvdata->csdev;
spin_lock(&drvdata->spinlock);
@@ -171,7 +172,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) writel_relaxed(0, drvdata->base + CTICONTROL); config->hw_enabled = false;
- coresight_disclaim_device_unlocked(drvdata->base); + coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base); spin_unlock(&drvdata->spinlock); pm_runtime_put(dev); @@ -645,6 +646,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, void *v) { struct cti_drvdata *drvdata; + struct coresight_device *csdev; unsigned int cpu = smp_processor_id(); int notify_res = NOTIFY_OK;
@@ -652,6 +654,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, return NOTIFY_OK;
drvdata = cti_cpu_drvdata[cpu]; + csdev = drvdata->csdev;
if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu)) return NOTIFY_BAD; @@ -663,13 +666,13 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, /* CTI regs all static - we have a copy & nothing to save */ drvdata->config.hw_powered = false; if (drvdata->config.hw_enabled) - coresight_disclaim_device(drvdata->base); + coresight_disclaim_device(csdev); break;
case CPU_PM_ENTER_FAILED: drvdata->config.hw_powered = true; if (drvdata->config.hw_enabled) { - if (coresight_claim_device(drvdata->base)) + if (coresight_claim_device(csdev)) drvdata->config.hw_enabled = false; } break; @@ -682,7 +685,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, /* check enable reference count to enable HW */ if (atomic_read(&drvdata->config.enable_req_count)) { /* check we can claim the device as we re-power */ - if (coresight_claim_device(drvdata->base)) + if (coresight_claim_device(csdev)) goto cti_notify_exit;
drvdata->config.hw_enabled = true; @@ -726,7 +729,7 @@ static int cti_dying_cpu(unsigned int cpu) spin_lock(&drvdata->spinlock); drvdata->config.hw_powered = false; if (drvdata->config.hw_enabled) - coresight_disclaim_device(drvdata->base); + coresight_disclaim_device(drvdata->csdev); spin_unlock(&drvdata->spinlock); return 0; } diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 2786d02dd23b..5b0d1c1a0442 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -132,7 +132,7 @@ static void __etb_enable_hw(struct etb_drvdata *drvdata)
static int etb_enable_hw(struct etb_drvdata *drvdata) { - int rc = coresight_claim_device(drvdata->base); + int rc = coresight_claim_device(drvdata->csdev);
if (rc) return rc; @@ -344,7 +344,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata) { __etb_disable_hw(drvdata); etb_dump_hw(drvdata); - coresight_disclaim_device(drvdata->base); + coresight_disclaim_device(drvdata->csdev); }
static int etb_disable(struct coresight_device *csdev) diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index e3724d8adecb..a7c791f15da7 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -360,10 +360,11 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) int i, rc; u32 etmcr; struct etm_config *config = &drvdata->config; + struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
- rc = coresight_claim_device_unlocked(drvdata->base); + rc = coresight_claim_device_unlocked(csdev); if (rc) goto done;
@@ -568,6 +569,7 @@ static void etm_disable_hw(void *info) int i; struct etm_drvdata *drvdata = info; struct etm_config *config = &drvdata->config; + struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base); etm_set_prog(drvdata); @@ -579,7 +581,7 @@ static void etm_disable_hw(void *info) config->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));
etm_set_pwrdwn(drvdata); - coresight_disclaim_device_unlocked(drvdata->base); + coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
@@ -604,7 +606,7 @@ static void etm_disable_perf(struct coresight_device *csdev) * power down the tracer. */ etm_set_pwrdwn(drvdata); - coresight_disclaim_device_unlocked(drvdata->base); + coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base); } diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 973fb0fd4826..5b81d6f12027 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -115,7 +115,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
etm4_os_unlock(drvdata);
- rc = coresight_claim_device_unlocked(drvdata->base); + rc = coresight_claim_device_unlocked(csdev); if (rc) goto done;
@@ -519,7 +519,7 @@ static void etm4_disable_hw(void *info) readl_relaxed(drvdata->base + TRCCNTVRn(i)); }
- coresight_disclaim_device_unlocked(drvdata->base); + coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index e8e233cbc130..b3f98ce51a68 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -52,13 +52,14 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) { u32 functl; int rc = 0; + struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); /* Claim the device only when we enable the first slave */ if (!(functl & FUNNEL_ENSx_MASK)) { - rc = coresight_claim_device_unlocked(drvdata->base); + rc = coresight_claim_device_unlocked(csdev); if (rc) goto done; } @@ -101,6 +102,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata, int inport) { u32 functl; + struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
@@ -110,7 +112,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,
/* Disclaim the device if none of the slaves are now active */ if (!(functl & FUNNEL_ENSx_MASK)) - coresight_disclaim_device_unlocked(drvdata->base); + coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base); } diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 8ba9cbe1d108..b8361bb808f1 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -45,12 +45,18 @@ struct replicator_drvdata {
static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) { + struct coresight_device *csdev = drvdata->csdev; CS_UNLOCK(drvdata->base);
- if (!coresight_claim_device_unlocked(drvdata->base)) { + if (WARN_ON(!csdev)) + return; + + CS_UNLOCK(drvdata->base); + + if (!coresight_claim_device_unlocked(csdev)) { writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0); writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1); - coresight_disclaim_device_unlocked(drvdata->base); + coresight_disclaim_device_unlocked(csdev); }
CS_LOCK(drvdata->base); @@ -70,6 +76,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, { int rc = 0; u32 id0val, id1val; + struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
@@ -84,7 +91,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, id0val = id1val = 0xff;
if (id0val == 0xff && id1val == 0xff) - rc = coresight_claim_device_unlocked(drvdata->base); + rc = coresight_claim_device_unlocked(csdev);
if (!rc) { switch (outport) { @@ -140,6 +147,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata, int inport, int outport) { u32 reg; + struct coresight_device *csdev = drvdata->csdev;
switch (outport) { case 0: @@ -160,7 +168,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) && (readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff)) - coresight_disclaim_device_unlocked(drvdata->base); + coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base); }
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 6375504ba8b0..610a494efbbc 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -37,7 +37,7 @@ static void __tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) { - int rc = coresight_claim_device(drvdata->base); + int rc = coresight_claim_device(drvdata->csdev);
if (rc) return rc; @@ -88,7 +88,7 @@ static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata) static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata) { __tmc_etb_disable_hw(drvdata); - coresight_disclaim_device(drvdata->base); + coresight_disclaim_device(drvdata->csdev); }
static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata) @@ -109,7 +109,7 @@ static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) { - int rc = coresight_claim_device(drvdata->base); + int rc = coresight_claim_device(drvdata->csdev);
if (rc) return rc; @@ -120,11 +120,13 @@ static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata) { + struct coresight_device *csdev = drvdata->csdev; + CS_UNLOCK(drvdata->base);
tmc_flush_and_stop(drvdata); tmc_disable_hw(drvdata); - coresight_disclaim_device_unlocked(drvdata->base); + coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base); }
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index b29c2db94d96..1aae2405041d 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1021,7 +1021,7 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, rc = tmc_etr_enable_catu(drvdata, etr_buf); if (rc) return rc; - rc = coresight_claim_device(drvdata->base); + rc = coresight_claim_device(drvdata->csdev); if (!rc) { drvdata->etr_buf = etr_buf; __tmc_etr_enable_hw(drvdata); @@ -1115,7 +1115,7 @@ void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) __tmc_etr_disable_hw(drvdata); /* Disable CATU device if this ETR is connected to one */ tmc_etr_disable_catu(drvdata); - coresight_disclaim_device(drvdata->base); + coresight_disclaim_device(drvdata->csdev); /* Reset the ETR buf used by hardware */ drvdata->etr_buf = NULL; } diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 21e7615fcbc8..7545a22769c4 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -130,30 +130,32 @@ static int coresight_find_link_outport(struct coresight_device *csdev, return -ENODEV; }
-static inline u32 coresight_read_claim_tags(void __iomem *base) +static inline u32 coresight_read_claim_tags(struct coresight_device *csdev) { - return readl_relaxed(base + CORESIGHT_CLAIMCLR); + return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR); }
-static inline bool coresight_is_claimed_self_hosted(void __iomem *base) +static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev) { - return coresight_read_claim_tags(base) == CORESIGHT_CLAIM_SELF_HOSTED; + return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED; }
-static inline bool coresight_is_claimed_any(void __iomem *base) +static inline bool coresight_is_claimed_any(struct coresight_device *csdev) { - return coresight_read_claim_tags(base) != 0; + return coresight_read_claim_tags(csdev) != 0; }
-static inline void coresight_set_claim_tags(void __iomem *base) +static inline void coresight_set_claim_tags(struct coresight_device *csdev) { - writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMSET); + csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED, + CORESIGHT_CLAIMSET); isb(); }
-static inline void coresight_clear_claim_tags(void __iomem *base) +static inline void coresight_clear_claim_tags(struct coresight_device *csdev) { - writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMCLR); + csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED, + CORESIGHT_CLAIMCLR); isb(); }
@@ -167,26 +169,32 @@ static inline void coresight_clear_claim_tags(void __iomem *base) * Called with CS_UNLOCKed for the component. * Returns : 0 on success */ -int coresight_claim_device_unlocked(void __iomem *base) +int coresight_claim_device_unlocked(struct coresight_device *csdev) { - if (coresight_is_claimed_any(base)) + if (WARN_ON(!csdev)) + return -EINVAL; + + if (coresight_is_claimed_any(csdev)) return -EBUSY;
- coresight_set_claim_tags(base); - if (coresight_is_claimed_self_hosted(base)) + coresight_set_claim_tags(csdev); + if (coresight_is_claimed_self_hosted(csdev)) return 0; /* There was a race setting the tags, clean up and fail */ - coresight_clear_claim_tags(base); + coresight_clear_claim_tags(csdev); return -EBUSY; }
-int coresight_claim_device(void __iomem *base) +int coresight_claim_device(struct coresight_device *csdev) { int rc;
- CS_UNLOCK(base); - rc = coresight_claim_device_unlocked(base); - CS_LOCK(base); + if (WARN_ON(!csdev)) + return -EINVAL; + + CS_UNLOCK(csdev->access.base); + rc = coresight_claim_device_unlocked(csdev); + CS_LOCK(csdev->access.base);
return rc; } @@ -195,11 +203,14 @@ int coresight_claim_device(void __iomem *base) * coresight_disclaim_device_unlocked : Clear the claim tags for the device. * Called with CS_UNLOCKed for the component. */ -void coresight_disclaim_device_unlocked(void __iomem *base) +void coresight_disclaim_device_unlocked(struct coresight_device *csdev) {
- if (coresight_is_claimed_self_hosted(base)) - coresight_clear_claim_tags(base); + if (WARN_ON(!csdev)) + return; + + if (coresight_is_claimed_self_hosted(csdev)) + coresight_clear_claim_tags(csdev); else /* * The external agent may have not honoured our claim @@ -209,11 +220,14 @@ void coresight_disclaim_device_unlocked(void __iomem *base) WARN_ON_ONCE(1); }
-void coresight_disclaim_device(void __iomem *base) +void coresight_disclaim_device(struct coresight_device *csdev) { - CS_UNLOCK(base); - coresight_disclaim_device_unlocked(base); - CS_LOCK(base); + if (WARN_ON(!csdev)) + return; + + CS_UNLOCK(csdev->access.base); + coresight_disclaim_device_unlocked(csdev); + CS_LOCK(csdev->access.base); }
/* enable or disable an associated CTI device of the supplied CS device */ diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 55a9c3276a28..811fdc21075a 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -473,11 +473,11 @@ extern int coresight_timeout(struct csdev_access *csa, int position, int value);
-extern int coresight_claim_device(void __iomem *base); -extern int coresight_claim_device_unlocked(void __iomem *base); +extern int coresight_claim_device(struct coresight_device *csdev); +extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
-extern void coresight_disclaim_device(void __iomem *base); -extern void coresight_disclaim_device_unlocked(void __iomem *base); +extern void coresight_disclaim_device(struct coresight_device *csdev); +extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev); extern char *coresight_alloc_device_name(struct coresight_dev_list *devs, struct device *dev);
@@ -512,18 +512,18 @@ static inline int coresight_timeout(struct csdev_access *csa, return 1; }
-static inline int coresight_claim_device_unlocked(void __iomem *base) +static inline int coresight_claim_device_unlocked(struct coresight_device *csdev) { return -EINVAL; }
-static inline int coresight_claim_device(void __iomem *base) +static inline int coresight_claim_device(struct coresight_device *csdev) { return -EINVAL; }
-static inline void coresight_disclaim_device(void __iomem *base) {} -static inline void coresight_disclaim_device_unlocked(void __iomem *base) {} +static inline void coresight_disclaim_device(struct coresight_device *csdev) {} +static inline void coresight_disclaim_device_unlocked(struct coresight_device *csdev) {}
static inline bool coresight_loses_context_with_cpu(struct device *dev) {
Reviewed-by: Mike Leach mike.leach@linaro.org
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Convert the generic CLAIM tag management APIs to use the device access layer abstraction.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-catu.c | 6 +- drivers/hwtracing/coresight/coresight-cti.c | 17 +++-- drivers/hwtracing/coresight/coresight-etb10.c | 4 +- drivers/hwtracing/coresight/coresight-etm3x.c | 8 ++- drivers/hwtracing/coresight/coresight-etm4x.c | 4 +- .../hwtracing/coresight/coresight-funnel.c | 6 +- .../coresight/coresight-replicator.c | 16 +++-- .../hwtracing/coresight/coresight-tmc-etf.c | 10 +-- .../hwtracing/coresight/coresight-tmc-etr.c | 4 +- drivers/hwtracing/coresight/coresight.c | 66 +++++++++++-------- include/linux/coresight.h | 16 ++--- 11 files changed, 95 insertions(+), 62 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 15e63e52ff23..df2f45457e2b 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -412,6 +412,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data) u32 control, mode; struct etr_buf *etr_buf = data; struct device *dev = &drvdata->csdev->dev;
struct coresight_device *csdev = drvdata->csdev; if (catu_wait_for_ready(drvdata)) dev_warn(dev, "Timeout while waiting for READY\n");
@@ -422,7 +423,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data) return -EBUSY; }
rc = coresight_claim_device_unlocked(drvdata->base);
rc = coresight_claim_device_unlocked(csdev); if (rc) return rc;
@@ -466,9 +467,10 @@ static int catu_disable_hw(struct catu_drvdata *drvdata) { int rc = 0; struct device *dev = &drvdata->csdev->dev;
struct coresight_device *csdev = drvdata->csdev; catu_write_control(drvdata, 0);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev); if (catu_wait_for_ready(drvdata)) { dev_info(dev, "Timeout while waiting for READY\n"); rc = -EAGAIN;
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index e13e24e4a858..e07e15593dd8 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -102,7 +102,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata) goto cti_state_unchanged;
/* claim the device */
rc = coresight_claim_device(drvdata->base);
rc = coresight_claim_device(drvdata->csdev); if (rc) goto cti_err_not_enabled;
@@ -136,7 +136,7 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata) goto cti_hp_not_enabled;
/* try to claim the device */
if (coresight_claim_device(drvdata->base))
if (coresight_claim_device(drvdata->csdev)) goto cti_hp_not_enabled; cti_write_all_hw_regs(drvdata);
@@ -154,6 +154,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) { struct cti_config *config = &drvdata->config; struct device *dev = &drvdata->csdev->dev;
struct coresight_device *csdev = drvdata->csdev; spin_lock(&drvdata->spinlock);
@@ -171,7 +172,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) writel_relaxed(0, drvdata->base + CTICONTROL); config->hw_enabled = false;
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base); spin_unlock(&drvdata->spinlock); pm_runtime_put(dev);
@@ -645,6 +646,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, void *v) { struct cti_drvdata *drvdata;
struct coresight_device *csdev; unsigned int cpu = smp_processor_id(); int notify_res = NOTIFY_OK;
@@ -652,6 +654,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, return NOTIFY_OK;
drvdata = cti_cpu_drvdata[cpu];
csdev = drvdata->csdev; if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu)) return NOTIFY_BAD;
@@ -663,13 +666,13 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, /* CTI regs all static - we have a copy & nothing to save */ drvdata->config.hw_powered = false; if (drvdata->config.hw_enabled)
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(csdev); break; case CPU_PM_ENTER_FAILED: drvdata->config.hw_powered = true; if (drvdata->config.hw_enabled) {
if (coresight_claim_device(drvdata->base))
if (coresight_claim_device(csdev)) drvdata->config.hw_enabled = false; } break;
@@ -682,7 +685,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, /* check enable reference count to enable HW */ if (atomic_read(&drvdata->config.enable_req_count)) { /* check we can claim the device as we re-power */
if (coresight_claim_device(drvdata->base))
if (coresight_claim_device(csdev)) goto cti_notify_exit; drvdata->config.hw_enabled = true;
@@ -726,7 +729,7 @@ static int cti_dying_cpu(unsigned int cpu) spin_lock(&drvdata->spinlock); drvdata->config.hw_powered = false; if (drvdata->config.hw_enabled)
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(drvdata->csdev); spin_unlock(&drvdata->spinlock); return 0;
} diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 2786d02dd23b..5b0d1c1a0442 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -132,7 +132,7 @@ static void __etb_enable_hw(struct etb_drvdata *drvdata)
static int etb_enable_hw(struct etb_drvdata *drvdata) {
int rc = coresight_claim_device(drvdata->base);
int rc = coresight_claim_device(drvdata->csdev); if (rc) return rc;
@@ -344,7 +344,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata) { __etb_disable_hw(drvdata); etb_dump_hw(drvdata);
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(drvdata->csdev);
}
static int etb_disable(struct coresight_device *csdev) diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index e3724d8adecb..a7c791f15da7 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -360,10 +360,11 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) int i, rc; u32 etmcr; struct etm_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev; CS_UNLOCK(drvdata->base);
rc = coresight_claim_device_unlocked(drvdata->base);
rc = coresight_claim_device_unlocked(csdev); if (rc) goto done;
@@ -568,6 +569,7 @@ static void etm_disable_hw(void *info) int i; struct etm_drvdata *drvdata = info; struct etm_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev; CS_UNLOCK(drvdata->base); etm_set_prog(drvdata);
@@ -579,7 +581,7 @@ static void etm_disable_hw(void *info) config->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));
etm_set_pwrdwn(drvdata);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base);
@@ -604,7 +606,7 @@ static void etm_disable_perf(struct coresight_device *csdev) * power down the tracer. */ etm_set_pwrdwn(drvdata);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base);
} diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 973fb0fd4826..5b81d6f12027 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -115,7 +115,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
etm4_os_unlock(drvdata);
rc = coresight_claim_device_unlocked(drvdata->base);
rc = coresight_claim_device_unlocked(csdev); if (rc) goto done;
@@ -519,7 +519,7 @@ static void etm4_disable_hw(void *info) readl_relaxed(drvdata->base + TRCCNTVRn(i)); }
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base);
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index e8e233cbc130..b3f98ce51a68 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -52,13 +52,14 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) { u32 functl; int rc = 0;
struct coresight_device *csdev = drvdata->csdev; CS_UNLOCK(drvdata->base); functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); /* Claim the device only when we enable the first slave */ if (!(functl & FUNNEL_ENSx_MASK)) {
rc = coresight_claim_device_unlocked(drvdata->base);
rc = coresight_claim_device_unlocked(csdev); if (rc) goto done; }
@@ -101,6 +102,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata, int inport) { u32 functl;
struct coresight_device *csdev = drvdata->csdev; CS_UNLOCK(drvdata->base);
@@ -110,7 +112,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,
/* Disclaim the device if none of the slaves are now active */ if (!(functl & FUNNEL_ENSx_MASK))
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base);
} diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 8ba9cbe1d108..b8361bb808f1 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -45,12 +45,18 @@ struct replicator_drvdata {
static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) {
struct coresight_device *csdev = drvdata->csdev; CS_UNLOCK(drvdata->base);
if (!coresight_claim_device_unlocked(drvdata->base)) {
if (WARN_ON(!csdev))
return;
CS_UNLOCK(drvdata->base);
if (!coresight_claim_device_unlocked(csdev)) { writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0); writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev); } CS_LOCK(drvdata->base);
@@ -70,6 +76,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, { int rc = 0; u32 id0val, id1val;
struct coresight_device *csdev = drvdata->csdev; CS_UNLOCK(drvdata->base);
@@ -84,7 +91,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, id0val = id1val = 0xff;
if (id0val == 0xff && id1val == 0xff)
rc = coresight_claim_device_unlocked(drvdata->base);
rc = coresight_claim_device_unlocked(csdev); if (!rc) { switch (outport) {
@@ -140,6 +147,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata, int inport, int outport) { u32 reg;
struct coresight_device *csdev = drvdata->csdev; switch (outport) { case 0:
@@ -160,7 +168,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) && (readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff))
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base);
}
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 6375504ba8b0..610a494efbbc 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -37,7 +37,7 @@ static void __tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) {
int rc = coresight_claim_device(drvdata->base);
int rc = coresight_claim_device(drvdata->csdev); if (rc) return rc;
@@ -88,7 +88,7 @@ static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata) static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata) { __tmc_etb_disable_hw(drvdata);
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(drvdata->csdev);
}
static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata) @@ -109,7 +109,7 @@ static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) {
int rc = coresight_claim_device(drvdata->base);
int rc = coresight_claim_device(drvdata->csdev); if (rc) return rc;
@@ -120,11 +120,13 @@ static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata) {
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base); tmc_flush_and_stop(drvdata); tmc_disable_hw(drvdata);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev); CS_LOCK(drvdata->base);
}
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index b29c2db94d96..1aae2405041d 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -1021,7 +1021,7 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, rc = tmc_etr_enable_catu(drvdata, etr_buf); if (rc) return rc;
rc = coresight_claim_device(drvdata->base);
rc = coresight_claim_device(drvdata->csdev); if (!rc) { drvdata->etr_buf = etr_buf; __tmc_etr_enable_hw(drvdata);
@@ -1115,7 +1115,7 @@ void tmc_etr_disable_hw(struct tmc_drvdata *drvdata) __tmc_etr_disable_hw(drvdata); /* Disable CATU device if this ETR is connected to one */ tmc_etr_disable_catu(drvdata);
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(drvdata->csdev); /* Reset the ETR buf used by hardware */ drvdata->etr_buf = NULL;
} diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 21e7615fcbc8..7545a22769c4 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -130,30 +130,32 @@ static int coresight_find_link_outport(struct coresight_device *csdev, return -ENODEV; }
-static inline u32 coresight_read_claim_tags(void __iomem *base) +static inline u32 coresight_read_claim_tags(struct coresight_device *csdev) {
return readl_relaxed(base + CORESIGHT_CLAIMCLR);
return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
}
-static inline bool coresight_is_claimed_self_hosted(void __iomem *base) +static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev) {
return coresight_read_claim_tags(base) == CORESIGHT_CLAIM_SELF_HOSTED;
return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
}
-static inline bool coresight_is_claimed_any(void __iomem *base) +static inline bool coresight_is_claimed_any(struct coresight_device *csdev) {
return coresight_read_claim_tags(base) != 0;
return coresight_read_claim_tags(csdev) != 0;
}
-static inline void coresight_set_claim_tags(void __iomem *base) +static inline void coresight_set_claim_tags(struct coresight_device *csdev) {
writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMSET);
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
CORESIGHT_CLAIMSET); isb();
}
-static inline void coresight_clear_claim_tags(void __iomem *base) +static inline void coresight_clear_claim_tags(struct coresight_device *csdev) {
writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMCLR);
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
CORESIGHT_CLAIMCLR); isb();
}
@@ -167,26 +169,32 @@ static inline void coresight_clear_claim_tags(void __iomem *base)
- Called with CS_UNLOCKed for the component.
- Returns : 0 on success
*/ -int coresight_claim_device_unlocked(void __iomem *base) +int coresight_claim_device_unlocked(struct coresight_device *csdev) {
if (coresight_is_claimed_any(base))
if (WARN_ON(!csdev))
return -EINVAL;
if (coresight_is_claimed_any(csdev)) return -EBUSY;
coresight_set_claim_tags(base);
if (coresight_is_claimed_self_hosted(base))
coresight_set_claim_tags(csdev);
if (coresight_is_claimed_self_hosted(csdev)) return 0; /* There was a race setting the tags, clean up and fail */
coresight_clear_claim_tags(base);
coresight_clear_claim_tags(csdev); return -EBUSY;
}
-int coresight_claim_device(void __iomem *base) +int coresight_claim_device(struct coresight_device *csdev) { int rc;
CS_UNLOCK(base);
rc = coresight_claim_device_unlocked(base);
CS_LOCK(base);
if (WARN_ON(!csdev))
return -EINVAL;
CS_UNLOCK(csdev->access.base);
rc = coresight_claim_device_unlocked(csdev);
CS_LOCK(csdev->access.base); return rc;
} @@ -195,11 +203,14 @@ int coresight_claim_device(void __iomem *base)
- coresight_disclaim_device_unlocked : Clear the claim tags for the device.
- Called with CS_UNLOCKed for the component.
*/ -void coresight_disclaim_device_unlocked(void __iomem *base) +void coresight_disclaim_device_unlocked(struct coresight_device *csdev) {
if (coresight_is_claimed_self_hosted(base))
coresight_clear_claim_tags(base);
if (WARN_ON(!csdev))
return;
if (coresight_is_claimed_self_hosted(csdev))
coresight_clear_claim_tags(csdev); else /* * The external agent may have not honoured our claim
@@ -209,11 +220,14 @@ void coresight_disclaim_device_unlocked(void __iomem *base) WARN_ON_ONCE(1); }
-void coresight_disclaim_device(void __iomem *base) +void coresight_disclaim_device(struct coresight_device *csdev) {
CS_UNLOCK(base);
coresight_disclaim_device_unlocked(base);
CS_LOCK(base);
if (WARN_ON(!csdev))
return;
CS_UNLOCK(csdev->access.base);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(csdev->access.base);
}
/* enable or disable an associated CTI device of the supplied CS device */ diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 55a9c3276a28..811fdc21075a 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -473,11 +473,11 @@ extern int coresight_timeout(struct csdev_access *csa, int position, int value);
-extern int coresight_claim_device(void __iomem *base); -extern int coresight_claim_device_unlocked(void __iomem *base); +extern int coresight_claim_device(struct coresight_device *csdev); +extern int coresight_claim_device_unlocked(struct coresight_device *csdev);
-extern void coresight_disclaim_device(void __iomem *base); -extern void coresight_disclaim_device_unlocked(void __iomem *base); +extern void coresight_disclaim_device(struct coresight_device *csdev); +extern void coresight_disclaim_device_unlocked(struct coresight_device *csdev); extern char *coresight_alloc_device_name(struct coresight_dev_list *devs, struct device *dev);
@@ -512,18 +512,18 @@ static inline int coresight_timeout(struct csdev_access *csa, return 1; }
-static inline int coresight_claim_device_unlocked(void __iomem *base) +static inline int coresight_claim_device_unlocked(struct coresight_device *csdev) { return -EINVAL; }
-static inline int coresight_claim_device(void __iomem *base) +static inline int coresight_claim_device(struct coresight_device *csdev) { return -EINVAL; }
-static inline void coresight_disclaim_device(void __iomem *base) {} -static inline void coresight_disclaim_device_unlocked(void __iomem *base) {} +static inline void coresight_disclaim_device(struct coresight_device *csdev) {} +static inline void coresight_disclaim_device_unlocked(struct coresight_device *csdev) {}
static inline bool coresight_loses_context_with_cpu(struct device *dev) { -- 2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Convert CS_LOCK/UNLOCK operations to use the device access layer.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-catu.c | 12 +++-- .../hwtracing/coresight/coresight-cpu-debug.c | 22 +++++++-- .../hwtracing/coresight/coresight-cti-sysfs.c | 5 +- drivers/hwtracing/coresight/coresight-cti.c | 16 ++++--- drivers/hwtracing/coresight/coresight-etb10.c | 19 ++++---- .../coresight/coresight-etm3x-sysfs.c | 10 ++-- drivers/hwtracing/coresight/coresight-etm3x.c | 26 +++++++---- drivers/hwtracing/coresight/coresight-etm4x.c | 27 +++++++---- .../hwtracing/coresight/coresight-funnel.c | 15 +++--- drivers/hwtracing/coresight/coresight-priv.h | 9 ++-- .../coresight/coresight-replicator.c | 16 ++++--- drivers/hwtracing/coresight/coresight-stm.c | 46 ++++++++++++------- .../hwtracing/coresight/coresight-tmc-etf.c | 28 +++++++---- .../hwtracing/coresight/coresight-tmc-etr.c | 16 ++++--- drivers/hwtracing/coresight/coresight-tpiu.c | 9 ++-- drivers/hwtracing/coresight/coresight.c | 8 ++-- 16 files changed, 179 insertions(+), 105 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index df2f45457e2b..9e96cda2f924 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -456,10 +456,12 @@ static int catu_enable(struct coresight_device *csdev, void *data) { int rc; struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev); + struct csdev_access *csa = &csdev->access;
- CS_UNLOCK(catu_drvdata->base); + CS_UNLOCK(csa); rc = catu_enable_hw(catu_drvdata, data); - CS_LOCK(catu_drvdata->base); + CS_LOCK(csa); + return rc; }
@@ -484,10 +486,12 @@ static int catu_disable(struct coresight_device *csdev, void *__unused) { int rc; struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev); + struct csdev_access *csa = &csdev->access;
- CS_UNLOCK(catu_drvdata->base); + CS_UNLOCK(csa); rc = catu_disable_hw(catu_drvdata); - CS_LOCK(catu_drvdata->base); + CS_LOCK(csa); + return rc; }
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index 96544b348c27..5d5619284866 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -108,6 +108,20 @@ static bool debug_enable; module_param_named(enable, debug_enable, bool, 0600); MODULE_PARM_DESC(enable, "Control to enable coresight CPU debug functionality");
+static inline void coresight_debug_lock(struct debug_drvdata *drvdata) +{ + struct csdev_access dummy = CSDEV_ACCESS_IOMEM(drvdata->base); + + CS_LOCK(&dummy); +} + +static void coresight_debug_unlock(struct debug_drvdata *drvdata) +{ + struct csdev_access dummy = CSDEV_ACCESS_IOMEM(drvdata->base); + + CS_UNLOCK(&dummy); +} + static void debug_os_unlock(struct debug_drvdata *drvdata) { /* Unlocks the debug registers */ @@ -191,7 +205,7 @@ static void debug_read_regs(struct debug_drvdata *drvdata) { u32 save_edprcr;
- CS_UNLOCK(drvdata->base); + coresight_debug_unlock(drvdata);
/* Unlock os lock */ debug_os_unlock(drvdata); @@ -238,7 +252,7 @@ static void debug_read_regs(struct debug_drvdata *drvdata) /* Restore EDPRCR register */ writel_relaxed(save_edprcr, drvdata->base + EDPRCR);
- CS_LOCK(drvdata->base); + coresight_debug_lock(drvdata); }
#ifdef CONFIG_64BIT @@ -326,13 +340,13 @@ static void debug_init_arch_data(void *info) u32 mode, pcsr_offset; u32 eddevid, eddevid1;
- CS_UNLOCK(drvdata->base); + coresight_debug_unlock(drvdata);
/* Read device info */ eddevid = readl_relaxed(drvdata->base + EDDEVID); eddevid1 = readl_relaxed(drvdata->base + EDDEVID1);
- CS_LOCK(drvdata->base); + coresight_debug_lock(drvdata);
/* Parse implementation feature */ mode = eddevid & EDDEVID_PCSAMPLE_MODE; diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 392757f3a019..2208b5191042 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -220,14 +220,15 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf, u32 val = 0; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *config = &drvdata->config; + struct csdev_access *csa = &drvdata->csdev->access;
spin_lock(&drvdata->spinlock); if ((reg_offset >= 0) && cti_active(config)) { - CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa); val = readl_relaxed(drvdata->base + reg_offset); if (pcached_val) *pcached_val = val; - CS_LOCK(drvdata->base); + CS_LOCK(csa); } else if (pcached_val) { val = *pcached_val; } diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index e07e15593dd8..f921a9eeba81 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -60,10 +60,11 @@ DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys"); /* write set of regs to hardware - call with spinlock claimed */ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) { + struct csdev_access *csa = &drvdata->csdev->access; struct cti_config *config = &drvdata->config; int i;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
/* disable CTI before writing registers */ writel_relaxed(0, drvdata->base + CTICONTROL); @@ -83,7 +84,7 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) /* re-enable CTI */ writel_relaxed(1, drvdata->base + CTICONTROL);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
/* write regs to hardware and enable */ @@ -155,6 +156,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) struct cti_config *config = &drvdata->config; struct device *dev = &drvdata->csdev->dev; struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &csdev->access;
spin_lock(&drvdata->spinlock);
@@ -166,14 +168,14 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) if (!config->hw_enabled || !config->hw_powered) goto cti_not_disabled;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
/* disable CTI */ writel_relaxed(0, drvdata->base + CTICONTROL); config->hw_enabled = false;
coresight_disclaim_device_unlocked(csdev); - CS_LOCK(drvdata->base); + CS_LOCK(csa); spin_unlock(&drvdata->spinlock); pm_runtime_put(dev); return 0; @@ -186,9 +188,11 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value) { - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &drvdata->csdev->access; + + CS_UNLOCK(csa); writel_relaxed(value, drvdata->base + offset); - CS_LOCK(drvdata->base); + CS_LOCK(csa); }
void cti_write_intack(struct device *dev, u32 ackval) diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 5b0d1c1a0442..b41cd73585cc 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -106,8 +106,9 @@ static void __etb_enable_hw(struct etb_drvdata *drvdata) { int i; u32 depth; + struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
depth = drvdata->buffer_depth; /* reset write RAM pointer address */ @@ -127,7 +128,7 @@ static void __etb_enable_hw(struct etb_drvdata *drvdata) /* ETB trace capture enable */ writel_relaxed(ETB_CTL_CAPT_EN, drvdata->base + ETB_CTL_REG);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static int etb_enable_hw(struct etb_drvdata *drvdata) @@ -253,7 +254,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) struct device *dev = &drvdata->csdev->dev; struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
ffcr = readl_relaxed(drvdata->base + ETB_FFCR); /* stop formatter when a stop has completed */ @@ -276,7 +277,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) "timeout while waiting for Formatter to Stop\n"); }
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void etb_dump_hw(struct etb_drvdata *drvdata) @@ -288,8 +289,9 @@ static void etb_dump_hw(struct etb_drvdata *drvdata) u32 read_ptr, write_ptr; u32 frame_off, frame_endoff; struct device *dev = &drvdata->csdev->dev; + struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER); write_ptr = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER); @@ -337,7 +339,7 @@ static void etb_dump_hw(struct etb_drvdata *drvdata)
writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void etb_disable_hw(struct etb_drvdata *drvdata) @@ -435,6 +437,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, unsigned long offset, to_read = 0, flags; struct cs_buffers *buf = sink_config; struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + struct csdev_access *csa = &drvdata->csdev->access;
if (!buf) return 0; @@ -448,7 +451,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, goto out;
__etb_disable_hw(drvdata); - CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
/* unit is in words, not bytes */ read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER); @@ -563,7 +566,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, handle->head += to_read;
__etb_enable_hw(drvdata); - CS_LOCK(drvdata->base); + CS_LOCK(csa); out: spin_unlock_irqrestore(&drvdata->spinlock, flags);
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c index e8c7649f123e..3e379b3fcdfd 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c @@ -47,14 +47,15 @@ static ssize_t etmsr_show(struct device *dev, { unsigned long flags, val; struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct csdev_access *csa = &drvdata->csdev->access;
pm_runtime_get_sync(dev->parent); spin_lock_irqsave(&drvdata->spinlock, flags); - CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
val = etm_readl(drvdata, ETMSR);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(dev->parent);
@@ -939,6 +940,7 @@ static ssize_t seq_curr_state_show(struct device *dev, unsigned long val, flags; struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etm_config *config = &drvdata->config; + struct csdev_access *csa = &drvdata->csdev->access;
if (!local_read(&drvdata->mode)) { val = config->seq_curr_state; @@ -948,9 +950,9 @@ static ssize_t seq_curr_state_show(struct device *dev, pm_runtime_get_sync(dev->parent); spin_lock_irqsave(&drvdata->spinlock, flags);
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa); val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK); - CS_LOCK(drvdata->base); + CS_LOCK(csa);
spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(dev->parent); diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index a7c791f15da7..debb4dc15527 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -361,8 +361,9 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) u32 etmcr; struct etm_config *config = &drvdata->config; struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
rc = coresight_claim_device_unlocked(csdev); if (rc) @@ -424,7 +425,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) etm_clr_prog(drvdata);
done: - CS_LOCK(drvdata->base); + CS_LOCK(csa);
dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n", drvdata->cpu, rc); @@ -457,10 +458,12 @@ int etm_get_trace_id(struct etm_drvdata *drvdata) unsigned long flags; int trace_id = -1; struct device *etm_dev; + struct csdev_access *csa;
if (!drvdata) goto out;
+ csa = &drvdata->csdev->access; etm_dev = drvdata->csdev->dev.parent; if (!local_read(&drvdata->mode)) return drvdata->traceid; @@ -469,9 +472,9 @@ int etm_get_trace_id(struct etm_drvdata *drvdata)
spin_lock_irqsave(&drvdata->spinlock, flags);
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa); trace_id = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK); - CS_LOCK(drvdata->base); + CS_LOCK(csa);
spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(etm_dev); @@ -570,8 +573,9 @@ static void etm_disable_hw(void *info) struct etm_drvdata *drvdata = info; struct etm_config *config = &drvdata->config; struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa); etm_set_prog(drvdata);
/* Read back sequencer and counters for post trace analysis */ @@ -583,7 +587,7 @@ static void etm_disable_hw(void *info) etm_set_pwrdwn(drvdata); coresight_disclaim_device_unlocked(csdev);
- CS_LOCK(drvdata->base); + CS_LOCK(csa);
dev_dbg(&drvdata->csdev->dev, "cpu: %d disable smp call done\n", drvdata->cpu); @@ -592,11 +596,12 @@ static void etm_disable_hw(void *info) static void etm_disable_perf(struct coresight_device *csdev) { struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + struct csdev_access *csa = &drvdata->csdev->access;
if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) return;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
/* Setting the prog bit disables tracing immediately */ etm_set_prog(drvdata); @@ -608,7 +613,7 @@ static void etm_disable_perf(struct coresight_device *csdev) etm_set_pwrdwn(drvdata); coresight_disclaim_device_unlocked(csdev);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void etm_disable_sysfs(struct coresight_device *csdev) @@ -739,11 +744,12 @@ static void etm_init_arch_data(void *info) u32 etmidr; u32 etmccr; struct etm_drvdata *drvdata = info; + struct csdev_access csa = CSDEV_ACCESS_IOMEM(drvdata->base);
/* Make sure all registers are accessible */ etm_os_unlock(drvdata);
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(&csa);
/* First dummy read */ (void)etm_readl(drvdata, ETMPDSR); @@ -776,7 +782,7 @@ static void etm_init_arch_data(void *info)
etm_set_pwrdwn(drvdata); etm_clr_pwrup(drvdata); - CS_LOCK(drvdata->base); + CS_LOCK(&csa); }
static void etm_init_trace_id(struct etm_drvdata *drvdata) diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 5b81d6f12027..40d242d14ffa 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -111,7 +111,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) struct device *etm_dev = &csdev->dev; struct csdev_access *csa = &csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
etm4_os_unlock(drvdata);
@@ -222,7 +222,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) isb();
done: - CS_LOCK(drvdata->base); + CS_LOCK(csa);
dev_dbg(etm_dev, "cpu: %d enable smp call done: %d\n", drvdata->cpu, rc); @@ -479,7 +479,7 @@ static void etm4_disable_hw(void *info) struct csdev_access *csa = &csdev->access; int i;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
if (!drvdata->skip_power_up) { /* power can be removed from the trace unit now */ @@ -521,7 +521,7 @@ static void etm4_disable_hw(void *info)
coresight_disclaim_device_unlocked(csdev);
- CS_LOCK(drvdata->base); + CS_LOCK(csa);
dev_dbg(&drvdata->csdev->dev, "cpu: %d disable smp call done\n", drvdata->cpu); @@ -626,11 +626,12 @@ static void etm4_init_arch_data(void *info) u32 etmidr5; struct etmv4_drvdata *drvdata = info; int i; + struct csdev_access csa = CSDEV_ACCESS_IOMEM(drvdata->base);
/* Make sure all registers are accessible */ etm4_os_unlock(drvdata);
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(&csa);
/* find all capabilities of the tracing unit */ etmidr0 = readl_relaxed(drvdata->base + TRCIDR0); @@ -784,7 +785,7 @@ static void etm4_init_arch_data(void *info) drvdata->nrseqstate = BMVAL(etmidr5, 25, 27); /* NUMCNTR, bits[30:28] number of counters available for tracing */ drvdata->nr_cntr = BMVAL(etmidr5, 28, 30); - CS_LOCK(drvdata->base); + CS_LOCK(&csa); }
/* Set ELx trace filter access in the TRCVICTLR register */ @@ -1165,7 +1166,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) dsb(sy); isb();
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
/* Lock the OS lock to disable trace and external debugger access */ etm4_os_lock(drvdata); @@ -1273,7 +1274,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) drvdata->base + TRCPDCR);
out: - CS_LOCK(drvdata->base); + CS_LOCK(csa); return ret; }
@@ -1281,8 +1282,14 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) { int i; struct etmv4_save_state *state = drvdata->save_state; + struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa; + + if (WARN_ON(!csdev)) + return;
- CS_UNLOCK(drvdata->base); + csa = &csdev->access; + CS_UNLOCK(csa);
writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
@@ -1374,7 +1381,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
/* Unlock the OS lock to re-enable trace and external debug access */ etm4_os_unlock(drvdata); - CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index b3f98ce51a68..5b74dd0d0652 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -53,8 +53,9 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) u32 functl; int rc = 0; struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); /* Claim the device only when we enable the first slave */ @@ -70,7 +71,7 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL); writel_relaxed(drvdata->priority, drvdata->base + FUNNEL_PRICTL); done: - CS_LOCK(drvdata->base); + CS_LOCK(csa); return rc; }
@@ -103,8 +104,9 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata, { u32 functl; struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); functl &= ~(1 << inport); @@ -114,7 +116,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata, if (!(functl & FUNNEL_ENSx_MASK)) coresight_disclaim_device_unlocked(csdev);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void funnel_disable(struct coresight_device *csdev, int inport, @@ -174,10 +176,11 @@ static DEVICE_ATTR_RW(priority); static u32 get_funnel_ctrl_hw(struct funnel_drvdata *drvdata) { u32 functl; + struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa); functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); - CS_LOCK(drvdata->base); + CS_LOCK(csa);
return functl; } diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index f2dc625ea585..a87ce11a0ea6 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -108,19 +108,20 @@ static inline void coresight_insert_barrier_packet(void *buf) }
-static inline void CS_LOCK(void __iomem *addr) +static inline void CS_LOCK(struct csdev_access *csa) { do { /* Wait for things to settle */ mb(); - writel_relaxed(0x0, addr + CORESIGHT_LAR); + csdev_access_relaxed_write32(csa, 0x0, CORESIGHT_LAR); } while (0); }
-static inline void CS_UNLOCK(void __iomem *addr) +static inline void CS_UNLOCK(struct csdev_access *csa) { do { - writel_relaxed(CORESIGHT_UNLOCK, addr + CORESIGHT_LAR); + csdev_access_relaxed_write32(csa, CORESIGHT_UNLOCK, + CORESIGHT_LAR); /* Make sure everyone has seen this */ mb(); } while (0); diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index b8361bb808f1..b9b40822f3aa 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -46,12 +46,12 @@ struct replicator_drvdata { static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev; - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &csdev->access;
if (WARN_ON(!csdev)) return;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
if (!coresight_claim_device_unlocked(csdev)) { writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0); @@ -59,7 +59,7 @@ static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) coresight_disclaim_device_unlocked(csdev); }
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
/* @@ -77,8 +77,9 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, int rc = 0; u32 id0val, id1val; struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
id0val = readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0); id1val = readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1); @@ -113,7 +114,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, writel_relaxed(id1val, drvdata->base + REPLICATOR_IDFILTER1); }
- CS_LOCK(drvdata->base); + CS_LOCK(csa);
return rc; } @@ -148,6 +149,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata, { u32 reg; struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &csdev->access;
switch (outport) { case 0: @@ -161,7 +163,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata, return; }
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
/* disable the flow of ATB data through port */ writel_relaxed(0xff, drvdata->base + reg); @@ -169,7 +171,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata, if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) && (readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff)) coresight_disclaim_device_unlocked(csdev); - CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void replicator_disable(struct coresight_device *csdev, int inport, diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 9667c5c8f433..ddf90c76284c 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -148,7 +148,9 @@ struct stm_drvdata {
static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata) { - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &drvdata->csdev->access; + + CS_UNLOCK(csa);
writel_relaxed(drvdata->stmhebsr, drvdata->base + STMHEBSR); writel_relaxed(drvdata->stmheter, drvdata->base + STMHETER); @@ -157,29 +159,33 @@ static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata) 0x04, /* Error detection on event tracing */ drvdata->base + STMHEMCR);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void stm_port_enable_hw(struct stm_drvdata *drvdata) { - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &drvdata->csdev->access; + + CS_UNLOCK(csa); /* ATB trigger enable on direct writes to TRIG locations */ writel_relaxed(0x10, drvdata->base + STMSPTRIGCSR); writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR); writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void stm_enable_hw(struct stm_drvdata *drvdata) { + struct csdev_access *csa = &drvdata->csdev->access; + if (drvdata->stmheer) stm_hwevent_enable_hw(drvdata);
stm_port_enable_hw(drvdata);
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
/* 4096 byte between synchronisation packets */ writel_relaxed(0xFFF, drvdata->base + STMSYNCR); @@ -188,7 +194,7 @@ static void stm_enable_hw(struct stm_drvdata *drvdata) 0x01), /* global STM enable */ drvdata->base + STMTCSR);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static int stm_enable(struct coresight_device *csdev, @@ -218,36 +224,41 @@ static int stm_enable(struct coresight_device *csdev,
static void stm_hwevent_disable_hw(struct stm_drvdata *drvdata) { - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &drvdata->csdev->access; + + CS_UNLOCK(csa);
writel_relaxed(0x0, drvdata->base + STMHEMCR); writel_relaxed(0x0, drvdata->base + STMHEER); writel_relaxed(0x0, drvdata->base + STMHETER);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void stm_port_disable_hw(struct stm_drvdata *drvdata) { - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &drvdata->csdev->access; + + CS_UNLOCK(csa);
writel_relaxed(0x0, drvdata->base + STMSPER); writel_relaxed(0x0, drvdata->base + STMSPTRIGCSR);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void stm_disable_hw(struct stm_drvdata *drvdata) { u32 val; + struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
val = readl_relaxed(drvdata->base + STMTCSR); val &= ~0x1; /* clear global STM enable [0] */ writel_relaxed(val, drvdata->base + STMTCSR);
- CS_LOCK(drvdata->base); + CS_LOCK(csa);
stm_port_disable_hw(drvdata); if (drvdata->stmheer) @@ -538,6 +549,8 @@ static ssize_t port_select_store(struct device *dev, const char *buf, size_t size) { struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct csdev_access *csa = &drvdata->csdev->access; + unsigned long val, stmsper; int ret = 0;
@@ -549,13 +562,13 @@ static ssize_t port_select_store(struct device *dev, drvdata->stmspscr = val;
if (local_read(&drvdata->mode)) { - CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa); /* Process as per ARM's TRM recommendation */ stmsper = readl_relaxed(drvdata->base + STMSPER); writel_relaxed(0x0, drvdata->base + STMSPER); writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR); writel_relaxed(stmsper, drvdata->base + STMSPER); - CS_LOCK(drvdata->base); + CS_LOCK(csa); } spin_unlock(&drvdata->spinlock);
@@ -585,6 +598,7 @@ static ssize_t port_enable_store(struct device *dev, const char *buf, size_t size) { struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent); + struct csdev_access *csa = &drvdata->csdev->access; unsigned long val; int ret = 0;
@@ -596,9 +610,9 @@ static ssize_t port_enable_store(struct device *dev, drvdata->stmsper = val;
if (local_read(&drvdata->mode)) { - CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa); writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER); - CS_LOCK(drvdata->base); + CS_LOCK(csa); } spin_unlock(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 610a494efbbc..05f65bd08cb1 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -18,7 +18,9 @@ static int tmc_set_etf_buffer(struct coresight_device *csdev,
static void __tmc_etb_enable_hw(struct tmc_drvdata *drvdata) { - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &drvdata->csdev->access; + + CS_UNLOCK(csa);
/* Wait for TMCSReady bit to be set */ tmc_wait_for_tmcready(drvdata); @@ -32,7 +34,7 @@ static void __tmc_etb_enable_hw(struct tmc_drvdata *drvdata) writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG); tmc_enable_hw(drvdata);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) @@ -71,7 +73,9 @@ static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata) { - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &drvdata->csdev->access; + + CS_UNLOCK(csa);
tmc_flush_and_stop(drvdata); /* @@ -82,7 +86,7 @@ static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata) tmc_etb_dump_hw(drvdata); tmc_disable_hw(drvdata);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata) @@ -93,7 +97,9 @@ static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata) { - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &drvdata->csdev->access; + + CS_UNLOCK(csa);
/* Wait for TMCSReady bit to be set */ tmc_wait_for_tmcready(drvdata); @@ -104,7 +110,7 @@ static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata) writel_relaxed(0x0, drvdata->base + TMC_BUFWM); tmc_enable_hw(drvdata);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) @@ -121,13 +127,14 @@ static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev; + struct csdev_access *csa = &csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
tmc_flush_and_stop(drvdata); tmc_disable_hw(drvdata); coresight_disclaim_device_unlocked(csdev); - CS_LOCK(drvdata->base); + CS_LOCK(csa); }
/* @@ -452,6 +459,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, unsigned long offset, to_read = 0, flags; struct cs_buffers *buf = sink_config; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); + struct csdev_access *csa = &csdev->access;
if (!buf) return 0; @@ -466,7 +474,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, if (atomic_read(csdev->refcnt) != 1) goto out;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
tmc_flush_and_stop(drvdata);
@@ -551,7 +559,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, if (buf->snapshot) handle->head += to_read;
- CS_LOCK(drvdata->base); + CS_LOCK(csa); out: spin_unlock_irqrestore(&drvdata->spinlock, flags);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 1aae2405041d..d33b93deefcb 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -952,8 +952,9 @@ static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata) { u32 axictl, sts; struct etr_buf *etr_buf = drvdata->etr_buf; + struct csdev_access *csa = &drvdata->csdev->access;
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
/* Wait for TMCSReady bit to be set */ tmc_wait_for_tmcready(drvdata); @@ -995,7 +996,7 @@ static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata) writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG); tmc_enable_hw(drvdata);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); }
static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, @@ -1094,7 +1095,9 @@ static void tmc_etr_sync_sysfs_buf(struct tmc_drvdata *drvdata)
static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata) { - CS_UNLOCK(drvdata->base); + struct csdev_access *csa = &drvdata->csdev->access; + + CS_UNLOCK(csa);
tmc_flush_and_stop(drvdata); /* @@ -1106,7 +1109,7 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
tmc_disable_hw(drvdata);
- CS_LOCK(drvdata->base); + CS_LOCK(csa);
}
@@ -1482,6 +1485,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev, struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct etr_perf_buffer *etr_perf = config; struct etr_buf *etr_buf = etr_perf->etr_buf; + struct csdev_access *csa = &csdev->access;
spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -1497,12 +1501,12 @@ tmc_update_etr_buffer(struct coresight_device *csdev, goto out; }
- CS_UNLOCK(drvdata->base); + CS_UNLOCK(csa);
tmc_flush_and_stop(drvdata); tmc_sync_etr_buf(drvdata);
- CS_LOCK(drvdata->base); + CS_LOCK(csa); spin_unlock_irqrestore(&drvdata->spinlock, flags);
lost = etr_buf->full; diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 7dd8300cf6be..dd38be482c21 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -62,11 +62,11 @@ struct tpiu_drvdata {
static void tpiu_enable_hw(struct csdev_access *csa) { - CS_UNLOCK(csa->base); + CS_UNLOCK(csa);
/* TODO: fill this up */
- CS_LOCK(csa->base); + CS_LOCK(csa); }
static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused) @@ -79,7 +79,8 @@ static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused)
static void tpiu_disable_hw(struct csdev_access *csa) { - CS_UNLOCK(csa->base); + + CS_UNLOCK(csa);
/* Clear formatter and stop on flush */ csdev_access_relaxed_write32(csa, FFCR_STOP_FI, TPIU_FFCR); @@ -90,7 +91,7 @@ static void tpiu_disable_hw(struct csdev_access *csa) /* Wait for formatter to stop */ coresight_timeout(csa, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
- CS_LOCK(csa->base); + CS_LOCK(csa); }
static int tpiu_disable(struct coresight_device *csdev) diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 7545a22769c4..64353ee0a2bc 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -192,9 +192,9 @@ int coresight_claim_device(struct coresight_device *csdev) if (WARN_ON(!csdev)) return -EINVAL;
- CS_UNLOCK(csdev->access.base); + CS_UNLOCK(&csdev->access); rc = coresight_claim_device_unlocked(csdev); - CS_LOCK(csdev->access.base); + CS_LOCK(&csdev->access);
return rc; } @@ -225,9 +225,9 @@ void coresight_disclaim_device(struct coresight_device *csdev) if (WARN_ON(!csdev)) return;
- CS_UNLOCK(csdev->access.base); + CS_UNLOCK(&csdev->access); coresight_disclaim_device_unlocked(csdev); - CS_LOCK(csdev->access.base); + CS_LOCK(&csdev->access); }
/* enable or disable an associated CTI device of the supplied CS device */
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Convert CS_LOCK/UNLOCK operations to use the device access layer.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-catu.c | 12 +++-- .../hwtracing/coresight/coresight-cpu-debug.c | 22 +++++++-- .../hwtracing/coresight/coresight-cti-sysfs.c | 5 +- drivers/hwtracing/coresight/coresight-cti.c | 16 ++++--- drivers/hwtracing/coresight/coresight-etb10.c | 19 ++++---- .../coresight/coresight-etm3x-sysfs.c | 10 ++-- drivers/hwtracing/coresight/coresight-etm3x.c | 26 +++++++---- drivers/hwtracing/coresight/coresight-etm4x.c | 27 +++++++---- .../hwtracing/coresight/coresight-funnel.c | 15 +++--- drivers/hwtracing/coresight/coresight-priv.h | 9 ++-- .../coresight/coresight-replicator.c | 16 ++++--- drivers/hwtracing/coresight/coresight-stm.c | 46 ++++++++++++------- .../hwtracing/coresight/coresight-tmc-etf.c | 28 +++++++---- .../hwtracing/coresight/coresight-tmc-etr.c | 16 ++++--- drivers/hwtracing/coresight/coresight-tpiu.c | 9 ++-- drivers/hwtracing/coresight/coresight.c | 8 ++-- 16 files changed, 179 insertions(+), 105 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index df2f45457e2b..9e96cda2f924 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -456,10 +456,12 @@ static int catu_enable(struct coresight_device *csdev, void *data) { int rc; struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
struct csdev_access *csa = &csdev->access;
CS_UNLOCK(catu_drvdata->base);
CS_UNLOCK(csa); rc = catu_enable_hw(catu_drvdata, data);
CS_LOCK(catu_drvdata->base);
CS_LOCK(csa);
return rc;
}
@@ -484,10 +486,12 @@ static int catu_disable(struct coresight_device *csdev, void *__unused) { int rc; struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
struct csdev_access *csa = &csdev->access;
CS_UNLOCK(catu_drvdata->base);
CS_UNLOCK(csa); rc = catu_disable_hw(catu_drvdata);
CS_LOCK(catu_drvdata->base);
CS_LOCK(csa);
return rc;
}
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index 96544b348c27..5d5619284866 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -108,6 +108,20 @@ static bool debug_enable; module_param_named(enable, debug_enable, bool, 0600); MODULE_PARM_DESC(enable, "Control to enable coresight CPU debug functionality");
+static inline void coresight_debug_lock(struct debug_drvdata *drvdata) +{
struct csdev_access dummy = CSDEV_ACCESS_IOMEM(drvdata->base);
CS_LOCK(&dummy);
+}
+static void coresight_debug_unlock(struct debug_drvdata *drvdata) +{
struct csdev_access dummy = CSDEV_ACCESS_IOMEM(drvdata->base);
CS_UNLOCK(&dummy);
+}
Perhaps it's just me, but whenever I see "dummy" in code, I immediately think this is stubbed out and doing nothing.
static void debug_os_unlock(struct debug_drvdata *drvdata) { /* Unlocks the debug registers */ @@ -191,7 +205,7 @@ static void debug_read_regs(struct debug_drvdata *drvdata) { u32 save_edprcr;
CS_UNLOCK(drvdata->base);
coresight_debug_unlock(drvdata); /* Unlock os lock */ debug_os_unlock(drvdata);
@@ -238,7 +252,7 @@ static void debug_read_regs(struct debug_drvdata *drvdata) /* Restore EDPRCR register */ writel_relaxed(save_edprcr, drvdata->base + EDPRCR);
CS_LOCK(drvdata->base);
coresight_debug_lock(drvdata);
}
#ifdef CONFIG_64BIT @@ -326,13 +340,13 @@ static void debug_init_arch_data(void *info) u32 mode, pcsr_offset; u32 eddevid, eddevid1;
CS_UNLOCK(drvdata->base);
coresight_debug_unlock(drvdata); /* Read device info */ eddevid = readl_relaxed(drvdata->base + EDDEVID); eddevid1 = readl_relaxed(drvdata->base + EDDEVID1);
CS_LOCK(drvdata->base);
coresight_debug_lock(drvdata); /* Parse implementation feature */ mode = eddevid & EDDEVID_PCSAMPLE_MODE;
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c index 392757f3a019..2208b5191042 100644 --- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c @@ -220,14 +220,15 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf, u32 val = 0; struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent); struct cti_config *config = &drvdata->config;
struct csdev_access *csa = &drvdata->csdev->access; spin_lock(&drvdata->spinlock); if ((reg_offset >= 0) && cti_active(config)) {
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); val = readl_relaxed(drvdata->base + reg_offset); if (pcached_val) *pcached_val = val;
CS_LOCK(drvdata->base);
CS_LOCK(csa); } else if (pcached_val) { val = *pcached_val; }
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c index e07e15593dd8..f921a9eeba81 100644 --- a/drivers/hwtracing/coresight/coresight-cti.c +++ b/drivers/hwtracing/coresight/coresight-cti.c @@ -60,10 +60,11 @@ DEFINE_CORESIGHT_DEVLIST(cti_sys_devs, "cti_sys"); /* write set of regs to hardware - call with spinlock claimed */ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) {
struct csdev_access *csa = &drvdata->csdev->access; struct cti_config *config = &drvdata->config; int i;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); /* disable CTI before writing registers */ writel_relaxed(0, drvdata->base + CTICONTROL);
@@ -83,7 +84,7 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata) /* re-enable CTI */ writel_relaxed(1, drvdata->base + CTICONTROL);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
/* write regs to hardware and enable */ @@ -155,6 +156,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) struct cti_config *config = &drvdata->config; struct device *dev = &drvdata->csdev->dev; struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access; spin_lock(&drvdata->spinlock);
@@ -166,14 +168,14 @@ static int cti_disable_hw(struct cti_drvdata *drvdata) if (!config->hw_enabled || !config->hw_powered) goto cti_not_disabled;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); /* disable CTI */ writel_relaxed(0, drvdata->base + CTICONTROL); config->hw_enabled = false; coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
CS_LOCK(csa); spin_unlock(&drvdata->spinlock); pm_runtime_put(dev); return 0;
@@ -186,9 +188,11 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value) {
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(csa); writel_relaxed(value, drvdata->base + offset);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
void cti_write_intack(struct device *dev, u32 ackval) diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 5b0d1c1a0442..b41cd73585cc 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -106,8 +106,9 @@ static void __etb_enable_hw(struct etb_drvdata *drvdata) { int i; u32 depth;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); depth = drvdata->buffer_depth; /* reset write RAM pointer address */
@@ -127,7 +128,7 @@ static void __etb_enable_hw(struct etb_drvdata *drvdata) /* ETB trace capture enable */ writel_relaxed(ETB_CTL_CAPT_EN, drvdata->base + ETB_CTL_REG);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static int etb_enable_hw(struct etb_drvdata *drvdata) @@ -253,7 +254,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) struct device *dev = &drvdata->csdev->dev; struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); ffcr = readl_relaxed(drvdata->base + ETB_FFCR); /* stop formatter when a stop has completed */
@@ -276,7 +277,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata) "timeout while waiting for Formatter to Stop\n"); }
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void etb_dump_hw(struct etb_drvdata *drvdata) @@ -288,8 +289,9 @@ static void etb_dump_hw(struct etb_drvdata *drvdata) u32 read_ptr, write_ptr; u32 frame_off, frame_endoff; struct device *dev = &drvdata->csdev->dev;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER); write_ptr = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
@@ -337,7 +339,7 @@ static void etb_dump_hw(struct etb_drvdata *drvdata)
writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void etb_disable_hw(struct etb_drvdata *drvdata) @@ -435,6 +437,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, unsigned long offset, to_read = 0, flags; struct cs_buffers *buf = sink_config; struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct csdev_access *csa = &drvdata->csdev->access; if (!buf) return 0;
@@ -448,7 +451,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, goto out;
__etb_disable_hw(drvdata);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); /* unit is in words, not bytes */ read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
@@ -563,7 +566,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, handle->head += to_read;
__etb_enable_hw(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
out: spin_unlock_irqrestore(&drvdata->spinlock, flags);
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c index e8c7649f123e..3e379b3fcdfd 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c @@ -47,14 +47,15 @@ static ssize_t etmsr_show(struct device *dev, { unsigned long flags, val; struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct csdev_access *csa = &drvdata->csdev->access; pm_runtime_get_sync(dev->parent); spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); val = etm_readl(drvdata, ETMSR);
CS_LOCK(drvdata->base);
CS_LOCK(csa); spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(dev->parent);
@@ -939,6 +940,7 @@ static ssize_t seq_curr_state_show(struct device *dev, unsigned long val, flags; struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etm_config *config = &drvdata->config;
struct csdev_access *csa = &drvdata->csdev->access; if (!local_read(&drvdata->mode)) { val = config->seq_curr_state;
@@ -948,9 +950,9 @@ static ssize_t seq_curr_state_show(struct device *dev, pm_runtime_get_sync(dev->parent); spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
CS_LOCK(drvdata->base);
CS_LOCK(csa); spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(dev->parent);
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index a7c791f15da7..debb4dc15527 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -361,8 +361,9 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) u32 etmcr; struct etm_config *config = &drvdata->config; struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); rc = coresight_claim_device_unlocked(csdev); if (rc)
@@ -424,7 +425,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata) etm_clr_prog(drvdata);
done:
CS_LOCK(drvdata->base);
CS_LOCK(csa); dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n", drvdata->cpu, rc);
@@ -457,10 +458,12 @@ int etm_get_trace_id(struct etm_drvdata *drvdata) unsigned long flags; int trace_id = -1; struct device *etm_dev;
struct csdev_access *csa; if (!drvdata) goto out;
csa = &drvdata->csdev->access; etm_dev = drvdata->csdev->dev.parent; if (!local_read(&drvdata->mode)) return drvdata->traceid;
@@ -469,9 +472,9 @@ int etm_get_trace_id(struct etm_drvdata *drvdata)
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); trace_id = (etm_readl(drvdata, ETMTRACEIDR) & ETM_TRACEID_MASK);
CS_LOCK(drvdata->base);
CS_LOCK(csa); spin_unlock_irqrestore(&drvdata->spinlock, flags); pm_runtime_put(etm_dev);
@@ -570,8 +573,9 @@ static void etm_disable_hw(void *info) struct etm_drvdata *drvdata = info; struct etm_config *config = &drvdata->config; struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); etm_set_prog(drvdata); /* Read back sequencer and counters for post trace analysis */
@@ -583,7 +587,7 @@ static void etm_disable_hw(void *info) etm_set_pwrdwn(drvdata); coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
CS_LOCK(csa); dev_dbg(&drvdata->csdev->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
@@ -592,11 +596,12 @@ static void etm_disable_hw(void *info) static void etm_disable_perf(struct coresight_device *csdev) { struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct csdev_access *csa = &drvdata->csdev->access; if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) return;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); /* Setting the prog bit disables tracing immediately */ etm_set_prog(drvdata);
@@ -608,7 +613,7 @@ static void etm_disable_perf(struct coresight_device *csdev) etm_set_pwrdwn(drvdata); coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void etm_disable_sysfs(struct coresight_device *csdev) @@ -739,11 +744,12 @@ static void etm_init_arch_data(void *info) u32 etmidr; u32 etmccr; struct etm_drvdata *drvdata = info;
struct csdev_access csa = CSDEV_ACCESS_IOMEM(drvdata->base); /* Make sure all registers are accessible */ etm_os_unlock(drvdata);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(&csa); /* First dummy read */ (void)etm_readl(drvdata, ETMPDSR);
@@ -776,7 +782,7 @@ static void etm_init_arch_data(void *info)
etm_set_pwrdwn(drvdata); etm_clr_pwrup(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(&csa);
}
static void etm_init_trace_id(struct etm_drvdata *drvdata) diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 5b81d6f12027..40d242d14ffa 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -111,7 +111,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) struct device *etm_dev = &csdev->dev; struct csdev_access *csa = &csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); etm4_os_unlock(drvdata);
@@ -222,7 +222,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) isb();
done:
CS_LOCK(drvdata->base);
CS_LOCK(csa); dev_dbg(etm_dev, "cpu: %d enable smp call done: %d\n", drvdata->cpu, rc);
@@ -479,7 +479,7 @@ static void etm4_disable_hw(void *info) struct csdev_access *csa = &csdev->access; int i;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); if (!drvdata->skip_power_up) { /* power can be removed from the trace unit now */
@@ -521,7 +521,7 @@ static void etm4_disable_hw(void *info)
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
CS_LOCK(csa); dev_dbg(&drvdata->csdev->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
@@ -626,11 +626,12 @@ static void etm4_init_arch_data(void *info) u32 etmidr5; struct etmv4_drvdata *drvdata = info; int i;
struct csdev_access csa = CSDEV_ACCESS_IOMEM(drvdata->base); /* Make sure all registers are accessible */ etm4_os_unlock(drvdata);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(&csa); /* find all capabilities of the tracing unit */ etmidr0 = readl_relaxed(drvdata->base + TRCIDR0);
@@ -784,7 +785,7 @@ static void etm4_init_arch_data(void *info) drvdata->nrseqstate = BMVAL(etmidr5, 25, 27); /* NUMCNTR, bits[30:28] number of counters available for tracing */ drvdata->nr_cntr = BMVAL(etmidr5, 28, 30);
CS_LOCK(drvdata->base);
CS_LOCK(&csa);
}
/* Set ELx trace filter access in the TRCVICTLR register */ @@ -1165,7 +1166,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) dsb(sy); isb();
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); /* Lock the OS lock to disable trace and external debugger access */ etm4_os_lock(drvdata);
@@ -1273,7 +1274,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) drvdata->base + TRCPDCR);
out:
CS_LOCK(drvdata->base);
CS_LOCK(csa); return ret;
}
@@ -1281,8 +1282,14 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) { int i; struct etmv4_save_state *state = drvdata->save_state;
struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa;
if (WARN_ON(!csdev))
return;
CS_UNLOCK(drvdata->base);
csa = &csdev->access;
CS_UNLOCK(csa); writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
@@ -1374,7 +1381,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
/* Unlock the OS lock to re-enable trace and external debug access */ etm4_os_unlock(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index b3f98ce51a68..5b74dd0d0652 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -53,8 +53,9 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) u32 functl; int rc = 0; struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); /* Claim the device only when we enable the first slave */
@@ -70,7 +71,7 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port) writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL); writel_relaxed(drvdata->priority, drvdata->base + FUNNEL_PRICTL); done:
CS_LOCK(drvdata->base);
CS_LOCK(csa); return rc;
}
@@ -103,8 +104,9 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata, { u32 functl; struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL); functl &= ~(1 << inport);
@@ -114,7 +116,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata, if (!(functl & FUNNEL_ENSx_MASK)) coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void funnel_disable(struct coresight_device *csdev, int inport, @@ -174,10 +176,11 @@ static DEVICE_ATTR_RW(priority); static u32 get_funnel_ctrl_hw(struct funnel_drvdata *drvdata) { u32 functl;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
CS_LOCK(drvdata->base);
CS_LOCK(csa); return functl;
} diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index f2dc625ea585..a87ce11a0ea6 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -108,19 +108,20 @@ static inline void coresight_insert_barrier_packet(void *buf) }
-static inline void CS_LOCK(void __iomem *addr) +static inline void CS_LOCK(struct csdev_access *csa) { do { /* Wait for things to settle */ mb();
writel_relaxed(0x0, addr + CORESIGHT_LAR);
csdev_access_relaxed_write32(csa, 0x0, CORESIGHT_LAR); } while (0);
}
-static inline void CS_UNLOCK(void __iomem *addr) +static inline void CS_UNLOCK(struct csdev_access *csa) { do {
writel_relaxed(CORESIGHT_UNLOCK, addr + CORESIGHT_LAR);
csdev_access_relaxed_write32(csa, CORESIGHT_UNLOCK,
CORESIGHT_LAR); /* Make sure everyone has seen this */ mb(); } while (0);
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index b8361bb808f1..b9b40822f3aa 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -46,12 +46,12 @@ struct replicator_drvdata { static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &csdev->access; if (WARN_ON(!csdev)) return;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); if (!coresight_claim_device_unlocked(csdev)) { writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0);
@@ -59,7 +59,7 @@ static void dynamic_replicator_reset(struct replicator_drvdata *drvdata) coresight_disclaim_device_unlocked(csdev); }
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
/* @@ -77,8 +77,9 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, int rc = 0; u32 id0val, id1val; struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); id0val = readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0); id1val = readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1);
@@ -113,7 +114,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata, writel_relaxed(id1val, drvdata->base + REPLICATOR_IDFILTER1); }
CS_LOCK(drvdata->base);
CS_LOCK(csa); return rc;
} @@ -148,6 +149,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata, { u32 reg; struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access; switch (outport) { case 0:
@@ -161,7 +163,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata, return; }
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); /* disable the flow of ATB data through port */ writel_relaxed(0xff, drvdata->base + reg);
@@ -169,7 +171,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata, if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) && (readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff)) coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void replicator_disable(struct coresight_device *csdev, int inport, diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 9667c5c8f433..ddf90c76284c 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -148,7 +148,9 @@ struct stm_drvdata {
static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata) {
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(csa); writel_relaxed(drvdata->stmhebsr, drvdata->base + STMHEBSR); writel_relaxed(drvdata->stmheter, drvdata->base + STMHETER);
@@ -157,29 +159,33 @@ static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata) 0x04, /* Error detection on event tracing */ drvdata->base + STMHEMCR);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void stm_port_enable_hw(struct stm_drvdata *drvdata) {
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(csa); /* ATB trigger enable on direct writes to TRIG locations */ writel_relaxed(0x10, drvdata->base + STMSPTRIGCSR); writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR); writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void stm_enable_hw(struct stm_drvdata *drvdata) {
struct csdev_access *csa = &drvdata->csdev->access;
if (drvdata->stmheer) stm_hwevent_enable_hw(drvdata); stm_port_enable_hw(drvdata);
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); /* 4096 byte between synchronisation packets */ writel_relaxed(0xFFF, drvdata->base + STMSYNCR);
@@ -188,7 +194,7 @@ static void stm_enable_hw(struct stm_drvdata *drvdata) 0x01), /* global STM enable */ drvdata->base + STMTCSR);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static int stm_enable(struct coresight_device *csdev, @@ -218,36 +224,41 @@ static int stm_enable(struct coresight_device *csdev,
static void stm_hwevent_disable_hw(struct stm_drvdata *drvdata) {
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(csa); writel_relaxed(0x0, drvdata->base + STMHEMCR); writel_relaxed(0x0, drvdata->base + STMHEER); writel_relaxed(0x0, drvdata->base + STMHETER);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void stm_port_disable_hw(struct stm_drvdata *drvdata) {
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(csa); writel_relaxed(0x0, drvdata->base + STMSPER); writel_relaxed(0x0, drvdata->base + STMSPTRIGCSR);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void stm_disable_hw(struct stm_drvdata *drvdata) { u32 val;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); val = readl_relaxed(drvdata->base + STMTCSR); val &= ~0x1; /* clear global STM enable [0] */ writel_relaxed(val, drvdata->base + STMTCSR);
CS_LOCK(drvdata->base);
CS_LOCK(csa); stm_port_disable_hw(drvdata); if (drvdata->stmheer)
@@ -538,6 +549,8 @@ static ssize_t port_select_store(struct device *dev, const char *buf, size_t size) { struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct csdev_access *csa = &drvdata->csdev->access;
unsigned long val, stmsper; int ret = 0;
@@ -549,13 +562,13 @@ static ssize_t port_select_store(struct device *dev, drvdata->stmspscr = val;
if (local_read(&drvdata->mode)) {
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); /* Process as per ARM's TRM recommendation */ stmsper = readl_relaxed(drvdata->base + STMSPER); writel_relaxed(0x0, drvdata->base + STMSPER); writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR); writel_relaxed(stmsper, drvdata->base + STMSPER);
CS_LOCK(drvdata->base);
CS_LOCK(csa); } spin_unlock(&drvdata->spinlock);
@@ -585,6 +598,7 @@ static ssize_t port_enable_store(struct device *dev, const char *buf, size_t size) { struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct csdev_access *csa = &drvdata->csdev->access; unsigned long val; int ret = 0;
@@ -596,9 +610,9 @@ static ssize_t port_enable_store(struct device *dev, drvdata->stmsper = val;
if (local_read(&drvdata->mode)) {
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);
CS_LOCK(drvdata->base);
CS_LOCK(csa); } spin_unlock(&drvdata->spinlock);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 610a494efbbc..05f65bd08cb1 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -18,7 +18,9 @@ static int tmc_set_etf_buffer(struct coresight_device *csdev,
static void __tmc_etb_enable_hw(struct tmc_drvdata *drvdata) {
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(csa); /* Wait for TMCSReady bit to be set */ tmc_wait_for_tmcready(drvdata);
@@ -32,7 +34,7 @@ static void __tmc_etb_enable_hw(struct tmc_drvdata *drvdata) writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG); tmc_enable_hw(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata) @@ -71,7 +73,9 @@ static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata) {
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(csa); tmc_flush_and_stop(drvdata); /*
@@ -82,7 +86,7 @@ static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata) tmc_etb_dump_hw(drvdata); tmc_disable_hw(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata) @@ -93,7 +97,9 @@ static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata) {
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(csa); /* Wait for TMCSReady bit to be set */ tmc_wait_for_tmcready(drvdata);
@@ -104,7 +110,7 @@ static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata) writel_relaxed(0x0, drvdata->base + TMC_BUFWM); tmc_enable_hw(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) @@ -121,13 +127,14 @@ static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata) static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata) { struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); tmc_flush_and_stop(drvdata); tmc_disable_hw(drvdata); coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
/* @@ -452,6 +459,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, unsigned long offset, to_read = 0, flags; struct cs_buffers *buf = sink_config; struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct csdev_access *csa = &csdev->access; if (!buf) return 0;
@@ -466,7 +474,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, if (atomic_read(csdev->refcnt) != 1) goto out;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); tmc_flush_and_stop(drvdata);
@@ -551,7 +559,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, if (buf->snapshot) handle->head += to_read;
CS_LOCK(drvdata->base);
CS_LOCK(csa);
out: spin_unlock_irqrestore(&drvdata->spinlock, flags);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 1aae2405041d..d33b93deefcb 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -952,8 +952,9 @@ static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata) { u32 axictl, sts; struct etr_buf *etr_buf = drvdata->etr_buf;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); /* Wait for TMCSReady bit to be set */ tmc_wait_for_tmcready(drvdata);
@@ -995,7 +996,7 @@ static void __tmc_etr_enable_hw(struct tmc_drvdata *drvdata) writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG); tmc_enable_hw(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata, @@ -1094,7 +1095,9 @@ static void tmc_etr_sync_sysfs_buf(struct tmc_drvdata *drvdata)
static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata) {
CS_UNLOCK(drvdata->base);
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(csa); tmc_flush_and_stop(drvdata); /*
@@ -1106,7 +1109,7 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
tmc_disable_hw(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(csa);
}
@@ -1482,6 +1485,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev, struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); struct etr_perf_buffer *etr_perf = config; struct etr_buf *etr_buf = etr_perf->etr_buf;
struct csdev_access *csa = &csdev->access; spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -1497,12 +1501,12 @@ tmc_update_etr_buffer(struct coresight_device *csdev, goto out; }
CS_UNLOCK(drvdata->base);
CS_UNLOCK(csa); tmc_flush_and_stop(drvdata); tmc_sync_etr_buf(drvdata);
CS_LOCK(drvdata->base);
CS_LOCK(csa); spin_unlock_irqrestore(&drvdata->spinlock, flags); lost = etr_buf->full;
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 7dd8300cf6be..dd38be482c21 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -62,11 +62,11 @@ struct tpiu_drvdata {
static void tpiu_enable_hw(struct csdev_access *csa) {
CS_UNLOCK(csa->base);
CS_UNLOCK(csa); /* TODO: fill this up */
CS_LOCK(csa->base);
CS_LOCK(csa);
}
static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused) @@ -79,7 +79,8 @@ static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused)
static void tpiu_disable_hw(struct csdev_access *csa) {
CS_UNLOCK(csa->base);
CS_UNLOCK(csa); /* Clear formatter and stop on flush */ csdev_access_relaxed_write32(csa, FFCR_STOP_FI, TPIU_FFCR);
@@ -90,7 +91,7 @@ static void tpiu_disable_hw(struct csdev_access *csa) /* Wait for formatter to stop */ coresight_timeout(csa, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
CS_LOCK(csa->base);
CS_LOCK(csa);
}
static int tpiu_disable(struct coresight_device *csdev) diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 7545a22769c4..64353ee0a2bc 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -192,9 +192,9 @@ int coresight_claim_device(struct coresight_device *csdev) if (WARN_ON(!csdev)) return -EINVAL;
CS_UNLOCK(csdev->access.base);
CS_UNLOCK(&csdev->access); rc = coresight_claim_device_unlocked(csdev);
CS_LOCK(csdev->access.base);
CS_LOCK(&csdev->access); return rc;
} @@ -225,9 +225,9 @@ void coresight_disclaim_device(struct coresight_device *csdev) if (WARN_ON(!csdev)) return;
CS_UNLOCK(csdev->access.base);
CS_UNLOCK(&csdev->access); coresight_disclaim_device_unlocked(csdev);
CS_LOCK(csdev->access.base);
CS_LOCK(&csdev->access);
}
/* enable or disable an associated CTI device of the supplied CS device */
2.24.1
Reviewed by: Mike Leach mike.leach@linaro.org
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
On 09/18/2020 04:34 PM, Mike Leach wrote:
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Convert CS_LOCK/UNLOCK operations to use the device access layer.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index 96544b348c27..5d5619284866 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -108,6 +108,20 @@ static bool debug_enable; module_param_named(enable, debug_enable, bool, 0600); MODULE_PARM_DESC(enable, "Control to enable coresight CPU debug functionality");
+static inline void coresight_debug_lock(struct debug_drvdata *drvdata) +{
struct csdev_access dummy = CSDEV_ACCESS_IOMEM(drvdata->base);
CS_LOCK(&dummy);
+}
+static void coresight_debug_unlock(struct debug_drvdata *drvdata) +{
struct csdev_access dummy = CSDEV_ACCESS_IOMEM(drvdata->base);
CS_UNLOCK(&dummy);
+}
Perhaps it's just me, but whenever I see "dummy" in code, I immediately think this is stubbed out and doing nothing.
No, you are not alone. I will change it to something sensible.
Reviewed by: Mike Leach mike.leach@linaro.org
Thanks for the review
Suzuki
As we are about to add support for sysreg access to ETM4.4+ components, make sure that we read the registers only on the host CPU.
Cc: Mike Leach mike.leach@linaro.org Reviewed-by: Mathieu Poirier mathieu.poirier@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- .../coresight/coresight-etm4x-sysfs.c | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index a588cd6de01c..57fc8dad2e92 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -2341,23 +2341,20 @@ static u32 etmv4_cross_read(const struct device *dev, u32 offset) return reg.data; }
-#define coresight_etm4x_reg(name, offset) \ - coresight_simple_reg32(struct etmv4_drvdata, name, offset) - #define coresight_etm4x_cross_read(name, offset) \ coresight_simple_func(struct etmv4_drvdata, etmv4_cross_read, \ name, offset)
-coresight_etm4x_reg(trcpdcr, TRCPDCR); -coresight_etm4x_reg(trcpdsr, TRCPDSR); -coresight_etm4x_reg(trclsr, TRCLSR); -coresight_etm4x_reg(trcauthstatus, TRCAUTHSTATUS); -coresight_etm4x_reg(trcdevid, TRCDEVID); -coresight_etm4x_reg(trcdevtype, TRCDEVTYPE); -coresight_etm4x_reg(trcpidr0, TRCPIDR0); -coresight_etm4x_reg(trcpidr1, TRCPIDR1); -coresight_etm4x_reg(trcpidr2, TRCPIDR2); -coresight_etm4x_reg(trcpidr3, TRCPIDR3); +coresight_etm4x_cross_read(trcpdcr, TRCPDCR); +coresight_etm4x_cross_read(trcpdsr, TRCPDSR); +coresight_etm4x_cross_read(trclsr, TRCLSR); +coresight_etm4x_cross_read(trcauthstatus, TRCAUTHSTATUS); +coresight_etm4x_cross_read(trcdevid, TRCDEVID); +coresight_etm4x_cross_read(trcdevtype, TRCDEVTYPE); +coresight_etm4x_cross_read(trcpidr0, TRCPIDR0); +coresight_etm4x_cross_read(trcpidr1, TRCPIDR1); +coresight_etm4x_cross_read(trcpidr2, TRCPIDR2); +coresight_etm4x_cross_read(trcpidr3, TRCPIDR3); coresight_etm4x_cross_read(trcoslsr, TRCOSLSR); coresight_etm4x_cross_read(trcconfig, TRCCONFIGR); coresight_etm4x_cross_read(trctraceid, TRCTRACEIDR);
Reviewed-by: Mike Leach mike.leach@linaro.org
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
As we are about to add support for sysreg access to ETM4.4+ components, make sure that we read the registers only on the host CPU.
Cc: Mike Leach mike.leach@linaro.org Reviewed-by: Mathieu Poirier mathieu.poirier@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
.../coresight/coresight-etm4x-sysfs.c | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index a588cd6de01c..57fc8dad2e92 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -2341,23 +2341,20 @@ static u32 etmv4_cross_read(const struct device *dev, u32 offset) return reg.data; }
-#define coresight_etm4x_reg(name, offset) \
coresight_simple_reg32(struct etmv4_drvdata, name, offset)
#define coresight_etm4x_cross_read(name, offset) \ coresight_simple_func(struct etmv4_drvdata, etmv4_cross_read, \ name, offset)
-coresight_etm4x_reg(trcpdcr, TRCPDCR); -coresight_etm4x_reg(trcpdsr, TRCPDSR); -coresight_etm4x_reg(trclsr, TRCLSR); -coresight_etm4x_reg(trcauthstatus, TRCAUTHSTATUS); -coresight_etm4x_reg(trcdevid, TRCDEVID); -coresight_etm4x_reg(trcdevtype, TRCDEVTYPE); -coresight_etm4x_reg(trcpidr0, TRCPIDR0); -coresight_etm4x_reg(trcpidr1, TRCPIDR1); -coresight_etm4x_reg(trcpidr2, TRCPIDR2); -coresight_etm4x_reg(trcpidr3, TRCPIDR3); +coresight_etm4x_cross_read(trcpdcr, TRCPDCR); +coresight_etm4x_cross_read(trcpdsr, TRCPDSR); +coresight_etm4x_cross_read(trclsr, TRCLSR); +coresight_etm4x_cross_read(trcauthstatus, TRCAUTHSTATUS); +coresight_etm4x_cross_read(trcdevid, TRCDEVID); +coresight_etm4x_cross_read(trcdevtype, TRCDEVTYPE); +coresight_etm4x_cross_read(trcpidr0, TRCPIDR0); +coresight_etm4x_cross_read(trcpidr1, TRCPIDR1); +coresight_etm4x_cross_read(trcpidr2, TRCPIDR2); +coresight_etm4x_cross_read(trcpidr3, TRCPIDR3); coresight_etm4x_cross_read(trcoslsr, TRCOSLSR); coresight_etm4x_cross_read(trcconfig, TRCCONFIGR); coresight_etm4x_cross_read(trctraceid, TRCTRACEIDR); -- 2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Convert all register accesses from etm4x driver to use a wrapper to allow switching the access at runtime with little overhead.
co-developed by sed tool ;-), mostly equivalent to :
s/readl(_relaxed)?(drvdata->base + (.*))/etm4x_\1_read32(csdev, \2) s/writel(_relaxed)?((.*), drvdata->base + (.*))/etm4x_\1_write32(csdev, \2, \3)
We don't want to replace them with the csdev_access_* to avoid a function call for every register access for system register access. This is a prepartory step to add system register access later where the support is available.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- .../coresight/coresight-etm4x-sysfs.c | 9 +- drivers/hwtracing/coresight/coresight-etm4x.c | 324 +++++++++--------- drivers/hwtracing/coresight/coresight-etm4x.h | 24 ++ 3 files changed, 184 insertions(+), 173 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index 57fc8dad2e92..321ad0dc09b0 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -2316,7 +2316,8 @@ static struct attribute *coresight_etmv4_attrs[] = { };
struct etmv4_reg { - void __iomem *addr; + struct coresight_device *csdev; + u32 offset; u32 data; };
@@ -2324,7 +2325,7 @@ static void do_smp_cross_read(void *data) { struct etmv4_reg *reg = data;
- reg->data = readl_relaxed(reg->addr); + reg->data = etm4x_relaxed_read32(®->csdev->access, reg->offset); }
static u32 etmv4_cross_read(const struct device *dev, u32 offset) @@ -2332,7 +2333,9 @@ 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; + reg.offset = offset; + reg.csdev = drvdata->csdev; + /* * smp cross call ensures the CPU will be powered up before * accessing the ETMv4 trace core registers diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 40d242d14ffa..f942f826d7b8 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -56,18 +56,28 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
static enum cpuhp_state hp_online;
-static void etm4_os_unlock(struct etmv4_drvdata *drvdata) +static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { /* Writing 0 to TRCOSLAR unlocks the trace registers */ - writel_relaxed(0x0, drvdata->base + TRCOSLAR); + etm4x_relaxed_write32(csa, 0x0, TRCOSLAR); drvdata->os_unlock = true; isb(); }
+static void etm4_os_unlock(struct etmv4_drvdata *drvdata) +{ + if (!WARN_ON(!drvdata->csdev)) + etm4_os_unlock_csa(drvdata, &drvdata->csdev->access); + +} + static void etm4_os_lock(struct etmv4_drvdata *drvdata) { + if (WARN_ON(!drvdata->csdev)) + return; + /* Writing 0x1 to TRCOSLAR locks the trace registers */ - writel_relaxed(0x1, drvdata->base + TRCOSLAR); + etm4x_relaxed_write32(&drvdata->csdev->access, 0x1, TRCOSLAR); drvdata->os_unlock = false; isb(); } @@ -120,44 +130,38 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) goto done;
/* Disable the trace unit before programming trace registers */ - writel_relaxed(0, drvdata->base + TRCPRGCTLR); + etm4x_relaxed_write32(csa, 0, TRCPRGCTLR);
/* wait for TRCSTATR.IDLE to go up */ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) dev_err(etm_dev, "timeout while waiting for Idle Trace Status\n");
- writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR); - writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR); + etm4x_relaxed_write32(csa, config->pe_sel, TRCPROCSELR); + etm4x_relaxed_write32(csa, config->cfg, TRCCONFIGR); /* nothing specific implemented */ - writel_relaxed(0x0, drvdata->base + TRCAUXCTLR); - writel_relaxed(config->eventctrl0, drvdata->base + TRCEVENTCTL0R); - writel_relaxed(config->eventctrl1, drvdata->base + TRCEVENTCTL1R); - writel_relaxed(config->stall_ctrl, drvdata->base + TRCSTALLCTLR); - writel_relaxed(config->ts_ctrl, drvdata->base + TRCTSCTLR); - writel_relaxed(config->syncfreq, drvdata->base + TRCSYNCPR); - writel_relaxed(config->ccctlr, drvdata->base + TRCCCCTLR); - writel_relaxed(config->bb_ctrl, drvdata->base + TRCBBCTLR); - writel_relaxed(drvdata->trcid, drvdata->base + TRCTRACEIDR); - writel_relaxed(config->vinst_ctrl, drvdata->base + TRCVICTLR); - writel_relaxed(config->viiectlr, drvdata->base + TRCVIIECTLR); - writel_relaxed(config->vissctlr, - drvdata->base + TRCVISSCTLR); - writel_relaxed(config->vipcssctlr, - drvdata->base + TRCVIPCSSCTLR); + etm4x_relaxed_write32(csa, 0x0, TRCAUXCTLR); + etm4x_relaxed_write32(csa, config->eventctrl0, TRCEVENTCTL0R); + etm4x_relaxed_write32(csa, config->eventctrl1, TRCEVENTCTL1R); + etm4x_relaxed_write32(csa, config->stall_ctrl, TRCSTALLCTLR); + etm4x_relaxed_write32(csa, config->ts_ctrl, TRCTSCTLR); + etm4x_relaxed_write32(csa, config->syncfreq, TRCSYNCPR); + etm4x_relaxed_write32(csa, config->ccctlr, TRCCCCTLR); + etm4x_relaxed_write32(csa, config->bb_ctrl, TRCBBCTLR); + etm4x_relaxed_write32(csa, drvdata->trcid, TRCTRACEIDR); + etm4x_relaxed_write32(csa, config->vinst_ctrl, TRCVICTLR); + etm4x_relaxed_write32(csa, config->viiectlr, TRCVIIECTLR); + etm4x_relaxed_write32(csa, config->vissctlr, TRCVISSCTLR); + etm4x_relaxed_write32(csa, config->vipcssctlr, TRCVIPCSSCTLR); for (i = 0; i < drvdata->nrseqstate - 1; i++) - writel_relaxed(config->seq_ctrl[i], - drvdata->base + TRCSEQEVRn(i)); - writel_relaxed(config->seq_rst, drvdata->base + TRCSEQRSTEVR); - writel_relaxed(config->seq_state, drvdata->base + TRCSEQSTR); - writel_relaxed(config->ext_inp, drvdata->base + TRCEXTINSELR); + etm4x_relaxed_write32(csa, config->seq_ctrl[i], TRCSEQEVRn(i)); + etm4x_relaxed_write32(csa, config->seq_rst, TRCSEQRSTEVR); + etm4x_relaxed_write32(csa, config->seq_state, TRCSEQSTR); + etm4x_relaxed_write32(csa, config->ext_inp, TRCEXTINSELR); for (i = 0; i < drvdata->nr_cntr; i++) { - writel_relaxed(config->cntrldvr[i], - drvdata->base + TRCCNTRLDVRn(i)); - writel_relaxed(config->cntr_ctrl[i], - drvdata->base + TRCCNTCTLRn(i)); - writel_relaxed(config->cntr_val[i], - drvdata->base + TRCCNTVRn(i)); + etm4x_relaxed_write32(csa, config->cntrldvr[i], TRCCNTRLDVRn(i)); + etm4x_relaxed_write32(csa, config->cntr_ctrl[i], TRCCNTCTLRn(i)); + etm4x_relaxed_write32(csa, config->cntr_val[i], TRCCNTVRn(i)); }
/* @@ -165,49 +169,42 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) * such start at 2. */ for (i = 2; i < drvdata->nr_resource * 2; i++) - writel_relaxed(config->res_ctrl[i], - drvdata->base + TRCRSCTLRn(i)); + etm4x_relaxed_write32(csa, config->res_ctrl[i], 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], - drvdata->base + TRCSSCSRn(i)); - writel_relaxed(config->ss_pe_cmp[i], - drvdata->base + TRCSSPCICRn(i)); + etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i)); + etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i)); + etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i)); } for (i = 0; i < drvdata->nr_addr_cmp; i++) { - writeq_relaxed(config->addr_val[i], - drvdata->base + TRCACVRn(i)); - writeq_relaxed(config->addr_acc[i], - drvdata->base + TRCACATRn(i)); + etm4x_relaxed_write64(csa, config->addr_val[i], TRCACVRn(i)); + etm4x_relaxed_write64(csa, config->addr_acc[i], TRCACATRn(i)); } for (i = 0; i < drvdata->numcidc; i++) - writeq_relaxed(config->ctxid_pid[i], - drvdata->base + TRCCIDCVRn(i)); - writel_relaxed(config->ctxid_mask0, drvdata->base + TRCCIDCCTLR0); - writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1); + etm4x_relaxed_write64(csa, config->ctxid_pid[i], TRCCIDCVRn(i)); + etm4x_relaxed_write32(csa, config->ctxid_mask0, TRCCIDCCTLR0); + etm4x_relaxed_write32(csa, config->ctxid_mask1, TRCCIDCCTLR1);
for (i = 0; i < drvdata->numvmidc; i++) - writeq_relaxed(config->vmid_val[i], - drvdata->base + TRCVMIDCVRn(i)); - writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0); - writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1); + etm4x_relaxed_write64(csa, config->vmid_val[i], TRCVMIDCVRn(i)); + etm4x_relaxed_write32(csa, config->vmid_mask0, TRCVMIDCCTLR0); + etm4x_relaxed_write32(csa, config->vmid_mask1, TRCVMIDCCTLR1);
if (!drvdata->skip_power_up) { + u32 trcpdcr = etm4x_relaxed_read32(csa, TRCPDCR); + /* * Request to keep the trace unit powered and also * emulation of powerdown */ - writel_relaxed(readl_relaxed(drvdata->base + TRCPDCR) | - TRCPDCR_PU, drvdata->base + TRCPDCR); + etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR); }
/* Enable the trace unit */ - writel_relaxed(1, drvdata->base + TRCPRGCTLR); + etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
/* wait for TRCSTATR.IDLE to go back down to '0' */ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) @@ -483,12 +480,12 @@ static void etm4_disable_hw(void *info)
if (!drvdata->skip_power_up) { /* power can be removed from the trace unit now */ - control = readl_relaxed(drvdata->base + TRCPDCR); + control = etm4x_relaxed_read32(csa, TRCPDCR); control &= ~TRCPDCR_PU; - writel_relaxed(control, drvdata->base + TRCPDCR); + etm4x_relaxed_write32(csa, control, TRCPDCR); }
- control = readl_relaxed(drvdata->base + TRCPRGCTLR); + control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
/* EN, bit[0] Trace unit enable bit */ control &= ~0x1; @@ -500,7 +497,7 @@ static void etm4_disable_hw(void *info) */ dsb(sy); isb(); - writel_relaxed(control, drvdata->base + TRCPRGCTLR); + etm4x_relaxed_write32(csa, control, TRCPRGCTLR);
/* wait for TRCSTATR.PMSTABLE to go to '1' */ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) @@ -510,13 +507,13 @@ static void etm4_disable_hw(void *info) /* 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)); + etm4x_relaxed_read32(csa, TRCSSCSRn(i)); }
/* read back the current counter values */ for (i = 0; i < drvdata->nr_cntr; i++) { config->cntr_val[i] = - readl_relaxed(drvdata->base + TRCCNTVRn(i)); + etm4x_relaxed_read32(csa, TRCCNTVRn(i)); }
coresight_disclaim_device_unlocked(csdev); @@ -545,7 +542,7 @@ static int etm4_disable_perf(struct coresight_device *csdev, * scheduled again. Configuration of the start/stop logic happens in * function etm4_set_event_filters(). */ - control = readl_relaxed(drvdata->base + TRCVICTLR); + control = etm4x_relaxed_read32(&csdev->access, TRCVICTLR); /* TRCVICTLR::SSSTATUS, bit[9] */ filters->ssstatus = (control & BIT(9));
@@ -629,12 +626,12 @@ static void etm4_init_arch_data(void *info) struct csdev_access csa = CSDEV_ACCESS_IOMEM(drvdata->base);
/* Make sure all registers are accessible */ - etm4_os_unlock(drvdata); + etm4_os_unlock_csa(drvdata, &csa);
CS_UNLOCK(&csa);
/* find all capabilities of the tracing unit */ - etmidr0 = readl_relaxed(drvdata->base + TRCIDR0); + etmidr0 = etm4x_relaxed_read32(&csa, TRCIDR0);
/* INSTP0, bits[2:1] P0 tracing support field */ if (BMVAL(etmidr0, 1, 1) && BMVAL(etmidr0, 2, 2)) @@ -674,7 +671,7 @@ static void etm4_init_arch_data(void *info) drvdata->ts_size = BMVAL(etmidr0, 24, 28);
/* base architecture of trace unit */ - etmidr1 = readl_relaxed(drvdata->base + TRCIDR1); + etmidr1 = etm4x_relaxed_read32(&csa, TRCIDR1); /* * TRCARCHMIN, bits[7:4] architecture the minor version number * TRCARCHMAJ, bits[11:8] architecture major versin number @@ -683,7 +680,7 @@ static void etm4_init_arch_data(void *info) drvdata->config.arch = drvdata->arch;
/* maximum size of resources */ - etmidr2 = readl_relaxed(drvdata->base + TRCIDR2); + etmidr2 = etm4x_relaxed_read32(&csa, TRCIDR2); /* CIDSIZE, bits[9:5] Indicates the Context ID size */ drvdata->ctxid_size = BMVAL(etmidr2, 5, 9); /* VMIDSIZE, bits[14:10] Indicates the VMID size */ @@ -691,7 +688,7 @@ static void etm4_init_arch_data(void *info) /* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */ drvdata->ccsize = BMVAL(etmidr2, 25, 28);
- etmidr3 = readl_relaxed(drvdata->base + TRCIDR3); + etmidr3 = etm4x_relaxed_read32(&csa, TRCIDR3); /* CCITMIN, bits[11:0] minimum threshold value that can be programmed */ drvdata->ccitmin = BMVAL(etmidr3, 0, 11); /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ @@ -736,7 +733,7 @@ static void etm4_init_arch_data(void *info) drvdata->nooverflow = false;
/* number of resources trace unit supports */ - etmidr4 = readl_relaxed(drvdata->base + TRCIDR4); + etmidr4 = etm4x_relaxed_read32(&csa, TRCIDR4); /* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */ drvdata->nr_addr_cmp = BMVAL(etmidr4, 0, 3); /* NUMPC, bits[15:12] number of PE comparator inputs for tracing */ @@ -756,14 +753,14 @@ static void etm4_init_arch_data(void *info) 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)); + etm4x_relaxed_read32(&csa, 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 */ drvdata->numvmidc = BMVAL(etmidr4, 28, 31);
- etmidr5 = readl_relaxed(drvdata->base + TRCIDR5); + etmidr5 = etm4x_relaxed_read32(&csa, TRCIDR5); /* NUMEXTIN, bits[8:0] number of external inputs implemented */ drvdata->nr_ext_inp = BMVAL(etmidr5, 0, 8); /* TRACEIDSIZE, bits[21:16] indicates the trace ID width */ @@ -1182,53 +1179,53 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state = drvdata->save_state;
- state->trcprgctlr = readl(drvdata->base + TRCPRGCTLR); - state->trcprocselr = readl(drvdata->base + TRCPROCSELR); - state->trcconfigr = readl(drvdata->base + TRCCONFIGR); - state->trcauxctlr = readl(drvdata->base + TRCAUXCTLR); - state->trceventctl0r = readl(drvdata->base + TRCEVENTCTL0R); - state->trceventctl1r = readl(drvdata->base + TRCEVENTCTL1R); - state->trcstallctlr = readl(drvdata->base + TRCSTALLCTLR); - state->trctsctlr = readl(drvdata->base + TRCTSCTLR); - state->trcsyncpr = readl(drvdata->base + TRCSYNCPR); - state->trcccctlr = readl(drvdata->base + TRCCCCTLR); - state->trcbbctlr = readl(drvdata->base + TRCBBCTLR); - state->trctraceidr = readl(drvdata->base + TRCTRACEIDR); - state->trcqctlr = readl(drvdata->base + TRCQCTLR); - - state->trcvictlr = readl(drvdata->base + TRCVICTLR); - state->trcviiectlr = readl(drvdata->base + TRCVIIECTLR); - state->trcvissctlr = readl(drvdata->base + TRCVISSCTLR); - state->trcvipcssctlr = readl(drvdata->base + TRCVIPCSSCTLR); - state->trcvdctlr = readl(drvdata->base + TRCVDCTLR); - state->trcvdsacctlr = readl(drvdata->base + TRCVDSACCTLR); - state->trcvdarcctlr = readl(drvdata->base + TRCVDARCCTLR); + state->trcprgctlr = etm4x_read32(csa, TRCPRGCTLR); + state->trcprocselr = etm4x_read32(csa, TRCPROCSELR); + state->trcconfigr = etm4x_read32(csa, TRCCONFIGR); + state->trcauxctlr = etm4x_read32(csa, TRCAUXCTLR); + state->trceventctl0r = etm4x_read32(csa, TRCEVENTCTL0R); + state->trceventctl1r = etm4x_read32(csa, TRCEVENTCTL1R); + state->trcstallctlr = etm4x_read32(csa, TRCSTALLCTLR); + state->trctsctlr = etm4x_read32(csa, TRCTSCTLR); + state->trcsyncpr = etm4x_read32(csa, TRCSYNCPR); + state->trcccctlr = etm4x_read32(csa, TRCCCCTLR); + state->trcbbctlr = etm4x_read32(csa, TRCBBCTLR); + state->trctraceidr = etm4x_read32(csa, TRCTRACEIDR); + state->trcqctlr = etm4x_read32(csa, TRCQCTLR); + + state->trcvictlr = etm4x_read32(csa, TRCVICTLR); + state->trcviiectlr = etm4x_read32(csa, TRCVIIECTLR); + state->trcvissctlr = etm4x_read32(csa, TRCVISSCTLR); + state->trcvipcssctlr = etm4x_read32(csa, TRCVIPCSSCTLR); + state->trcvdctlr = etm4x_read32(csa, TRCVDCTLR); + state->trcvdsacctlr = etm4x_read32(csa, TRCVDSACCTLR); + state->trcvdarcctlr = etm4x_read32(csa, TRCVDARCCTLR);
for (i = 0; i < drvdata->nrseqstate - 1; i++) - state->trcseqevr[i] = readl(drvdata->base + TRCSEQEVRn(i)); + state->trcseqevr[i] = etm4x_read32(csa, TRCSEQEVRn(i));
- state->trcseqrstevr = readl(drvdata->base + TRCSEQRSTEVR); - state->trcseqstr = readl(drvdata->base + TRCSEQSTR); - state->trcextinselr = readl(drvdata->base + TRCEXTINSELR); + state->trcseqrstevr = etm4x_read32(csa, TRCSEQRSTEVR); + state->trcseqstr = etm4x_read32(csa, TRCSEQSTR); + state->trcextinselr = etm4x_read32(csa, TRCEXTINSELR);
for (i = 0; i < drvdata->nr_cntr; i++) { - state->trccntrldvr[i] = readl(drvdata->base + TRCCNTRLDVRn(i)); - state->trccntctlr[i] = readl(drvdata->base + TRCCNTCTLRn(i)); - state->trccntvr[i] = readl(drvdata->base + TRCCNTVRn(i)); + state->trccntrldvr[i] = etm4x_read32(csa, TRCCNTRLDVRn(i)); + state->trccntctlr[i] = etm4x_read32(csa, TRCCNTCTLRn(i)); + state->trccntvr[i] = etm4x_read32(csa, TRCCNTVRn(i)); }
for (i = 0; i < drvdata->nr_resource * 2; i++) - state->trcrsctlr[i] = readl(drvdata->base + TRCRSCTLRn(i)); + state->trcrsctlr[i] = etm4x_read32(csa, TRCRSCTLRn(i));
for (i = 0; i < drvdata->nr_ss_cmp; i++) { - state->trcssccr[i] = readl(drvdata->base + TRCSSCCRn(i)); - state->trcsscsr[i] = readl(drvdata->base + TRCSSCSRn(i)); - state->trcsspcicr[i] = readl(drvdata->base + TRCSSPCICRn(i)); + state->trcssccr[i] = etm4x_read32(csa, TRCSSCCRn(i)); + state->trcsscsr[i] = etm4x_read32(csa, TRCSSCSRn(i)); + state->trcsspcicr[i] = etm4x_read32(csa, TRCSSPCICRn(i)); }
for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) { - state->trcacvr[i] = readq(drvdata->base + TRCACVRn(i)); - state->trcacatr[i] = readq(drvdata->base + TRCACATRn(i)); + state->trcacvr[i] = etm4x_read64(csa, TRCACVRn(i)); + state->trcacatr[i] = etm4x_read64(csa, TRCACATRn(i)); }
/* @@ -1239,20 +1236,20 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) */
for (i = 0; i < drvdata->numcidc; i++) - state->trccidcvr[i] = readq(drvdata->base + TRCCIDCVRn(i)); + state->trccidcvr[i] = etm4x_read64(csa, TRCCIDCVRn(i));
for (i = 0; i < drvdata->numvmidc; i++) - state->trcvmidcvr[i] = readq(drvdata->base + TRCVMIDCVRn(i)); + state->trcvmidcvr[i] = etm4x_read64(csa, TRCVMIDCVRn(i));
- state->trccidcctlr0 = readl(drvdata->base + TRCCIDCCTLR0); - state->trccidcctlr1 = readl(drvdata->base + TRCCIDCCTLR1); + state->trccidcctlr0 = etm4x_read32(csa, TRCCIDCCTLR0); + state->trccidcctlr1 = etm4x_read32(csa, TRCCIDCCTLR1);
- state->trcvmidcctlr0 = readl(drvdata->base + TRCVMIDCCTLR0); - state->trcvmidcctlr0 = readl(drvdata->base + TRCVMIDCCTLR1); + state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR0); + state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR1);
- state->trcclaimset = readl(drvdata->base + TRCCLAIMCLR); + state->trcclaimset = etm4x_read32(csa, TRCCLAIMCLR);
- state->trcpdcr = readl(drvdata->base + TRCPDCR); + state->trcpdcr = etm4x_read32(csa, TRCPDCR);
/* wait for TRCSTATR.IDLE to go up */ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) { @@ -1270,8 +1267,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) * potentially save power on systems that respect the TRCPDCR_PU * despite requesting software to save/restore state. */ - writel_relaxed((state->trcpdcr & ~TRCPDCR_PU), - drvdata->base + TRCPDCR); + etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU), TRCPDCR);
out: CS_LOCK(csa); @@ -1291,84 +1287,72 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) csa = &csdev->access; CS_UNLOCK(csa);
- writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET); - - writel_relaxed(state->trcprgctlr, drvdata->base + TRCPRGCTLR); - writel_relaxed(state->trcprocselr, drvdata->base + TRCPROCSELR); - writel_relaxed(state->trcconfigr, drvdata->base + TRCCONFIGR); - writel_relaxed(state->trcauxctlr, drvdata->base + TRCAUXCTLR); - writel_relaxed(state->trceventctl0r, drvdata->base + TRCEVENTCTL0R); - writel_relaxed(state->trceventctl1r, drvdata->base + TRCEVENTCTL1R); - writel_relaxed(state->trcstallctlr, drvdata->base + TRCSTALLCTLR); - writel_relaxed(state->trctsctlr, drvdata->base + TRCTSCTLR); - writel_relaxed(state->trcsyncpr, drvdata->base + TRCSYNCPR); - writel_relaxed(state->trcccctlr, drvdata->base + TRCCCCTLR); - writel_relaxed(state->trcbbctlr, drvdata->base + TRCBBCTLR); - writel_relaxed(state->trctraceidr, drvdata->base + TRCTRACEIDR); - writel_relaxed(state->trcqctlr, drvdata->base + TRCQCTLR); - - writel_relaxed(state->trcvictlr, drvdata->base + TRCVICTLR); - writel_relaxed(state->trcviiectlr, drvdata->base + TRCVIIECTLR); - writel_relaxed(state->trcvissctlr, drvdata->base + TRCVISSCTLR); - writel_relaxed(state->trcvipcssctlr, drvdata->base + TRCVIPCSSCTLR); - writel_relaxed(state->trcvdctlr, drvdata->base + TRCVDCTLR); - writel_relaxed(state->trcvdsacctlr, drvdata->base + TRCVDSACCTLR); - writel_relaxed(state->trcvdarcctlr, drvdata->base + TRCVDARCCTLR); + etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET); + + etm4x_relaxed_write32(csa, state->trcprgctlr, TRCPRGCTLR); + etm4x_relaxed_write32(csa, state->trcprocselr, TRCPROCSELR); + etm4x_relaxed_write32(csa, state->trcconfigr, TRCCONFIGR); + etm4x_relaxed_write32(csa, state->trcauxctlr, TRCAUXCTLR); + etm4x_relaxed_write32(csa, state->trceventctl0r, TRCEVENTCTL0R); + etm4x_relaxed_write32(csa, state->trceventctl1r, TRCEVENTCTL1R); + etm4x_relaxed_write32(csa, state->trcstallctlr, TRCSTALLCTLR); + etm4x_relaxed_write32(csa, state->trctsctlr, TRCTSCTLR); + etm4x_relaxed_write32(csa, state->trcsyncpr, TRCSYNCPR); + etm4x_relaxed_write32(csa, state->trcccctlr, TRCCCCTLR); + etm4x_relaxed_write32(csa, state->trcbbctlr, TRCBBCTLR); + etm4x_relaxed_write32(csa, state->trctraceidr, TRCTRACEIDR); + etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR); + + etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR); + etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR); + etm4x_relaxed_write32(csa, state->trcvissctlr, TRCVISSCTLR); + etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR); + etm4x_relaxed_write32(csa, state->trcvdctlr, TRCVDCTLR); + etm4x_relaxed_write32(csa, state->trcvdsacctlr, TRCVDSACCTLR); + etm4x_relaxed_write32(csa, state->trcvdarcctlr, TRCVDARCCTLR);
for (i = 0; i < drvdata->nrseqstate - 1; i++) - writel_relaxed(state->trcseqevr[i], - drvdata->base + TRCSEQEVRn(i)); + etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i));
- writel_relaxed(state->trcseqrstevr, drvdata->base + TRCSEQRSTEVR); - writel_relaxed(state->trcseqstr, drvdata->base + TRCSEQSTR); - writel_relaxed(state->trcextinselr, drvdata->base + TRCEXTINSELR); + etm4x_relaxed_write32(csa, state->trcseqrstevr, TRCSEQRSTEVR); + etm4x_relaxed_write32(csa, state->trcseqstr, TRCSEQSTR); + etm4x_relaxed_write32(csa, state->trcextinselr, TRCEXTINSELR);
for (i = 0; i < drvdata->nr_cntr; i++) { - writel_relaxed(state->trccntrldvr[i], - drvdata->base + TRCCNTRLDVRn(i)); - writel_relaxed(state->trccntctlr[i], - drvdata->base + TRCCNTCTLRn(i)); - writel_relaxed(state->trccntvr[i], - drvdata->base + TRCCNTVRn(i)); + etm4x_relaxed_write32(csa, state->trccntrldvr[i], TRCCNTRLDVRn(i)); + etm4x_relaxed_write32(csa, state->trccntctlr[i], TRCCNTCTLRn(i)); + etm4x_relaxed_write32(csa, state->trccntvr[i], TRCCNTVRn(i)); }
for (i = 0; i < drvdata->nr_resource * 2; i++) - writel_relaxed(state->trcrsctlr[i], - drvdata->base + TRCRSCTLRn(i)); + etm4x_relaxed_write32(csa, state->trcrsctlr[i], TRCRSCTLRn(i));
for (i = 0; i < drvdata->nr_ss_cmp; i++) { - writel_relaxed(state->trcssccr[i], - drvdata->base + TRCSSCCRn(i)); - writel_relaxed(state->trcsscsr[i], - drvdata->base + TRCSSCSRn(i)); - writel_relaxed(state->trcsspcicr[i], - drvdata->base + TRCSSPCICRn(i)); + etm4x_relaxed_write32(csa, state->trcssccr[i], TRCSSCCRn(i)); + etm4x_relaxed_write32(csa, state->trcsscsr[i], TRCSSCSRn(i)); + etm4x_relaxed_write32(csa, state->trcsspcicr[i], TRCSSPCICRn(i)); }
for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) { - writeq_relaxed(state->trcacvr[i], - drvdata->base + TRCACVRn(i)); - writeq_relaxed(state->trcacatr[i], - drvdata->base + TRCACATRn(i)); + etm4x_relaxed_write64(csa, state->trcacvr[i], TRCACVRn(i)); + etm4x_relaxed_write64(csa, state->trcacatr[i], TRCACATRn(i)); }
for (i = 0; i < drvdata->numcidc; i++) - writeq_relaxed(state->trccidcvr[i], - drvdata->base + TRCCIDCVRn(i)); + etm4x_relaxed_write64(csa, state->trccidcvr[i], TRCCIDCVRn(i));
for (i = 0; i < drvdata->numvmidc; i++) - writeq_relaxed(state->trcvmidcvr[i], - drvdata->base + TRCVMIDCVRn(i)); + etm4x_relaxed_write64(csa, state->trcvmidcvr[i], TRCVMIDCVRn(i));
- writel_relaxed(state->trccidcctlr0, drvdata->base + TRCCIDCCTLR0); - writel_relaxed(state->trccidcctlr1, drvdata->base + TRCCIDCCTLR1); + etm4x_relaxed_write32(csa, state->trccidcctlr0, TRCCIDCCTLR0); + etm4x_relaxed_write32(csa, state->trccidcctlr1, TRCCIDCCTLR1);
- writel_relaxed(state->trcvmidcctlr0, drvdata->base + TRCVMIDCCTLR0); - writel_relaxed(state->trcvmidcctlr0, drvdata->base + TRCVMIDCCTLR1); + etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR0); + etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR1);
- writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET); + etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
- writel_relaxed(state->trcpdcr, drvdata->base + TRCPDCR); + etm4x_relaxed_write32(csa, state->trcpdcr, TRCPDCR);
drvdata->state_needs_restore = false;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 5259f96fd28a..2746d3b591ca 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -120,6 +120,30 @@ #define TRCCIDR2 0xFF8 #define TRCCIDR3 0xFFC
+#define etm4x_relaxed_read32(csa, offset) \ + readl_relaxed((csa)->base + (offset)) + +#define etm4x_read32(csa, offset) \ + readl((csa)->base + (offset)) + +#define etm4x_relaxed_write32(csa, val, offset) \ + writel_relaxed((val), (csa)->base + (offset)) + +#define etm4x_write32(csa, val, offset) \ + writel((val), (csa)->base + (offset)) + +#define etm4x_relaxed_read64(csa, offset) \ + readq_relaxed((csa)->base + (offset)) + +#define etm4x_read64(csa, offset) \ + readq((csa)->base + (offset)) + +#define etm4x_relaxed_write64(csa, val, offset) \ + writeq_relaxed((val), (csa)->base + (offset)) + +#define etm4x_write64(csa, val, offset) \ + writeq((val), (csa)->base + (offset)) + /* ETMv4 resources */ #define ETM_MAX_NR_PE 8 #define ETMv4_MAX_CNTR 4
Reviewed-by: Mike Leach mike.leach@linaro.org
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Convert all register accesses from etm4x driver to use a wrapper to allow switching the access at runtime with little overhead.
co-developed by sed tool ;-), mostly equivalent to :
s/readl(_relaxed)?(drvdata->base + (.*))/etm4x_\1_read32(csdev, \2) s/writel(_relaxed)?((.*), drvdata->base + (.*))/etm4x_\1_write32(csdev, \2, \3)
We don't want to replace them with the csdev_access_* to avoid a function call for every register access for system register access. This is a prepartory step to add system register access later where the support is available.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
.../coresight/coresight-etm4x-sysfs.c | 9 +- drivers/hwtracing/coresight/coresight-etm4x.c | 324 +++++++++--------- drivers/hwtracing/coresight/coresight-etm4x.h | 24 ++ 3 files changed, 184 insertions(+), 173 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index 57fc8dad2e92..321ad0dc09b0 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -2316,7 +2316,8 @@ static struct attribute *coresight_etmv4_attrs[] = { };
struct etmv4_reg {
void __iomem *addr;
struct coresight_device *csdev;
u32 offset; u32 data;
};
@@ -2324,7 +2325,7 @@ static void do_smp_cross_read(void *data) { struct etmv4_reg *reg = data;
reg->data = readl_relaxed(reg->addr);
reg->data = etm4x_relaxed_read32(®->csdev->access, reg->offset);
}
static u32 etmv4_cross_read(const struct device *dev, u32 offset) @@ -2332,7 +2333,9 @@ 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;
reg.offset = offset;
reg.csdev = drvdata->csdev;
/* * smp cross call ensures the CPU will be powered up before * accessing the ETMv4 trace core registers
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 40d242d14ffa..f942f826d7b8 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -56,18 +56,28 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
static enum cpuhp_state hp_online;
-static void etm4_os_unlock(struct etmv4_drvdata *drvdata) +static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { /* Writing 0 to TRCOSLAR unlocks the trace registers */
writel_relaxed(0x0, drvdata->base + TRCOSLAR);
etm4x_relaxed_write32(csa, 0x0, TRCOSLAR); drvdata->os_unlock = true; isb();
}
+static void etm4_os_unlock(struct etmv4_drvdata *drvdata) +{
if (!WARN_ON(!drvdata->csdev))
etm4_os_unlock_csa(drvdata, &drvdata->csdev->access);
+}
static void etm4_os_lock(struct etmv4_drvdata *drvdata) {
if (WARN_ON(!drvdata->csdev))
return;
/* Writing 0x1 to TRCOSLAR locks the trace registers */
writel_relaxed(0x1, drvdata->base + TRCOSLAR);
etm4x_relaxed_write32(&drvdata->csdev->access, 0x1, TRCOSLAR); drvdata->os_unlock = false; isb();
} @@ -120,44 +130,38 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) goto done;
/* Disable the trace unit before programming trace registers */
writel_relaxed(0, drvdata->base + TRCPRGCTLR);
etm4x_relaxed_write32(csa, 0, TRCPRGCTLR); /* wait for TRCSTATR.IDLE to go up */ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) dev_err(etm_dev, "timeout while waiting for Idle Trace Status\n");
writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR);
etm4x_relaxed_write32(csa, config->pe_sel, TRCPROCSELR);
etm4x_relaxed_write32(csa, config->cfg, TRCCONFIGR); /* nothing specific implemented */
writel_relaxed(0x0, drvdata->base + TRCAUXCTLR);
writel_relaxed(config->eventctrl0, drvdata->base + TRCEVENTCTL0R);
writel_relaxed(config->eventctrl1, drvdata->base + TRCEVENTCTL1R);
writel_relaxed(config->stall_ctrl, drvdata->base + TRCSTALLCTLR);
writel_relaxed(config->ts_ctrl, drvdata->base + TRCTSCTLR);
writel_relaxed(config->syncfreq, drvdata->base + TRCSYNCPR);
writel_relaxed(config->ccctlr, drvdata->base + TRCCCCTLR);
writel_relaxed(config->bb_ctrl, drvdata->base + TRCBBCTLR);
writel_relaxed(drvdata->trcid, drvdata->base + TRCTRACEIDR);
writel_relaxed(config->vinst_ctrl, drvdata->base + TRCVICTLR);
writel_relaxed(config->viiectlr, drvdata->base + TRCVIIECTLR);
writel_relaxed(config->vissctlr,
drvdata->base + TRCVISSCTLR);
writel_relaxed(config->vipcssctlr,
drvdata->base + TRCVIPCSSCTLR);
etm4x_relaxed_write32(csa, 0x0, TRCAUXCTLR);
etm4x_relaxed_write32(csa, config->eventctrl0, TRCEVENTCTL0R);
etm4x_relaxed_write32(csa, config->eventctrl1, TRCEVENTCTL1R);
etm4x_relaxed_write32(csa, config->stall_ctrl, TRCSTALLCTLR);
etm4x_relaxed_write32(csa, config->ts_ctrl, TRCTSCTLR);
etm4x_relaxed_write32(csa, config->syncfreq, TRCSYNCPR);
etm4x_relaxed_write32(csa, config->ccctlr, TRCCCCTLR);
etm4x_relaxed_write32(csa, config->bb_ctrl, TRCBBCTLR);
etm4x_relaxed_write32(csa, drvdata->trcid, TRCTRACEIDR);
etm4x_relaxed_write32(csa, config->vinst_ctrl, TRCVICTLR);
etm4x_relaxed_write32(csa, config->viiectlr, TRCVIIECTLR);
etm4x_relaxed_write32(csa, config->vissctlr, TRCVISSCTLR);
etm4x_relaxed_write32(csa, config->vipcssctlr, TRCVIPCSSCTLR); for (i = 0; i < drvdata->nrseqstate - 1; i++)
writel_relaxed(config->seq_ctrl[i],
drvdata->base + TRCSEQEVRn(i));
writel_relaxed(config->seq_rst, drvdata->base + TRCSEQRSTEVR);
writel_relaxed(config->seq_state, drvdata->base + TRCSEQSTR);
writel_relaxed(config->ext_inp, drvdata->base + TRCEXTINSELR);
etm4x_relaxed_write32(csa, config->seq_ctrl[i], TRCSEQEVRn(i));
etm4x_relaxed_write32(csa, config->seq_rst, TRCSEQRSTEVR);
etm4x_relaxed_write32(csa, config->seq_state, TRCSEQSTR);
etm4x_relaxed_write32(csa, config->ext_inp, TRCEXTINSELR); for (i = 0; i < drvdata->nr_cntr; i++) {
writel_relaxed(config->cntrldvr[i],
drvdata->base + TRCCNTRLDVRn(i));
writel_relaxed(config->cntr_ctrl[i],
drvdata->base + TRCCNTCTLRn(i));
writel_relaxed(config->cntr_val[i],
drvdata->base + TRCCNTVRn(i));
etm4x_relaxed_write32(csa, config->cntrldvr[i], TRCCNTRLDVRn(i));
etm4x_relaxed_write32(csa, config->cntr_ctrl[i], TRCCNTCTLRn(i));
etm4x_relaxed_write32(csa, config->cntr_val[i], TRCCNTVRn(i)); } /*
@@ -165,49 +169,42 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) * such start at 2. */ for (i = 2; i < drvdata->nr_resource * 2; i++)
writel_relaxed(config->res_ctrl[i],
drvdata->base + TRCRSCTLRn(i));
etm4x_relaxed_write32(csa, config->res_ctrl[i], 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],
drvdata->base + TRCSSCSRn(i));
writel_relaxed(config->ss_pe_cmp[i],
drvdata->base + TRCSSPCICRn(i));
etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i));
etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i));
etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i)); } for (i = 0; i < drvdata->nr_addr_cmp; i++) {
writeq_relaxed(config->addr_val[i],
drvdata->base + TRCACVRn(i));
writeq_relaxed(config->addr_acc[i],
drvdata->base + TRCACATRn(i));
etm4x_relaxed_write64(csa, config->addr_val[i], TRCACVRn(i));
etm4x_relaxed_write64(csa, config->addr_acc[i], TRCACATRn(i)); } for (i = 0; i < drvdata->numcidc; i++)
writeq_relaxed(config->ctxid_pid[i],
drvdata->base + TRCCIDCVRn(i));
writel_relaxed(config->ctxid_mask0, drvdata->base + TRCCIDCCTLR0);
writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
etm4x_relaxed_write64(csa, config->ctxid_pid[i], TRCCIDCVRn(i));
etm4x_relaxed_write32(csa, config->ctxid_mask0, TRCCIDCCTLR0);
etm4x_relaxed_write32(csa, config->ctxid_mask1, TRCCIDCCTLR1); for (i = 0; i < drvdata->numvmidc; i++)
writeq_relaxed(config->vmid_val[i],
drvdata->base + TRCVMIDCVRn(i));
writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0);
writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
etm4x_relaxed_write64(csa, config->vmid_val[i], TRCVMIDCVRn(i));
etm4x_relaxed_write32(csa, config->vmid_mask0, TRCVMIDCCTLR0);
etm4x_relaxed_write32(csa, config->vmid_mask1, TRCVMIDCCTLR1); if (!drvdata->skip_power_up) {
u32 trcpdcr = etm4x_relaxed_read32(csa, TRCPDCR);
/* * Request to keep the trace unit powered and also * emulation of powerdown */
writel_relaxed(readl_relaxed(drvdata->base + TRCPDCR) |
TRCPDCR_PU, drvdata->base + TRCPDCR);
etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR); } /* Enable the trace unit */
writel_relaxed(1, drvdata->base + TRCPRGCTLR);
etm4x_relaxed_write32(csa, 1, TRCPRGCTLR); /* wait for TRCSTATR.IDLE to go back down to '0' */ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0))
@@ -483,12 +480,12 @@ static void etm4_disable_hw(void *info)
if (!drvdata->skip_power_up) { /* power can be removed from the trace unit now */
control = readl_relaxed(drvdata->base + TRCPDCR);
control = etm4x_relaxed_read32(csa, TRCPDCR); control &= ~TRCPDCR_PU;
writel_relaxed(control, drvdata->base + TRCPDCR);
etm4x_relaxed_write32(csa, control, TRCPDCR); }
control = readl_relaxed(drvdata->base + TRCPRGCTLR);
control = etm4x_relaxed_read32(csa, TRCPRGCTLR); /* EN, bit[0] Trace unit enable bit */ control &= ~0x1;
@@ -500,7 +497,7 @@ static void etm4_disable_hw(void *info) */ dsb(sy); isb();
writel_relaxed(control, drvdata->base + TRCPRGCTLR);
etm4x_relaxed_write32(csa, control, TRCPRGCTLR); /* wait for TRCSTATR.PMSTABLE to go to '1' */ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1))
@@ -510,13 +507,13 @@ static void etm4_disable_hw(void *info) /* 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));
etm4x_relaxed_read32(csa, TRCSSCSRn(i)); } /* read back the current counter values */ for (i = 0; i < drvdata->nr_cntr; i++) { config->cntr_val[i] =
readl_relaxed(drvdata->base + TRCCNTVRn(i));
etm4x_relaxed_read32(csa, TRCCNTVRn(i)); } coresight_disclaim_device_unlocked(csdev);
@@ -545,7 +542,7 @@ static int etm4_disable_perf(struct coresight_device *csdev, * scheduled again. Configuration of the start/stop logic happens in * function etm4_set_event_filters(). */
control = readl_relaxed(drvdata->base + TRCVICTLR);
control = etm4x_relaxed_read32(&csdev->access, TRCVICTLR); /* TRCVICTLR::SSSTATUS, bit[9] */ filters->ssstatus = (control & BIT(9));
@@ -629,12 +626,12 @@ static void etm4_init_arch_data(void *info) struct csdev_access csa = CSDEV_ACCESS_IOMEM(drvdata->base);
/* Make sure all registers are accessible */
etm4_os_unlock(drvdata);
etm4_os_unlock_csa(drvdata, &csa); CS_UNLOCK(&csa); /* find all capabilities of the tracing unit */
etmidr0 = readl_relaxed(drvdata->base + TRCIDR0);
etmidr0 = etm4x_relaxed_read32(&csa, TRCIDR0); /* INSTP0, bits[2:1] P0 tracing support field */ if (BMVAL(etmidr0, 1, 1) && BMVAL(etmidr0, 2, 2))
@@ -674,7 +671,7 @@ static void etm4_init_arch_data(void *info) drvdata->ts_size = BMVAL(etmidr0, 24, 28);
/* base architecture of trace unit */
etmidr1 = readl_relaxed(drvdata->base + TRCIDR1);
etmidr1 = etm4x_relaxed_read32(&csa, TRCIDR1); /* * TRCARCHMIN, bits[7:4] architecture the minor version number * TRCARCHMAJ, bits[11:8] architecture major versin number
@@ -683,7 +680,7 @@ static void etm4_init_arch_data(void *info) drvdata->config.arch = drvdata->arch;
/* maximum size of resources */
etmidr2 = readl_relaxed(drvdata->base + TRCIDR2);
etmidr2 = etm4x_relaxed_read32(&csa, TRCIDR2); /* CIDSIZE, bits[9:5] Indicates the Context ID size */ drvdata->ctxid_size = BMVAL(etmidr2, 5, 9); /* VMIDSIZE, bits[14:10] Indicates the VMID size */
@@ -691,7 +688,7 @@ static void etm4_init_arch_data(void *info) /* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */ drvdata->ccsize = BMVAL(etmidr2, 25, 28);
etmidr3 = readl_relaxed(drvdata->base + TRCIDR3);
etmidr3 = etm4x_relaxed_read32(&csa, TRCIDR3); /* CCITMIN, bits[11:0] minimum threshold value that can be programmed */ drvdata->ccitmin = BMVAL(etmidr3, 0, 11); /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */
@@ -736,7 +733,7 @@ static void etm4_init_arch_data(void *info) drvdata->nooverflow = false;
/* number of resources trace unit supports */
etmidr4 = readl_relaxed(drvdata->base + TRCIDR4);
etmidr4 = etm4x_relaxed_read32(&csa, TRCIDR4); /* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */ drvdata->nr_addr_cmp = BMVAL(etmidr4, 0, 3); /* NUMPC, bits[15:12] number of PE comparator inputs for tracing */
@@ -756,14 +753,14 @@ static void etm4_init_arch_data(void *info) 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));
etm4x_relaxed_read32(&csa, 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 */ drvdata->numvmidc = BMVAL(etmidr4, 28, 31);
etmidr5 = readl_relaxed(drvdata->base + TRCIDR5);
etmidr5 = etm4x_relaxed_read32(&csa, TRCIDR5); /* NUMEXTIN, bits[8:0] number of external inputs implemented */ drvdata->nr_ext_inp = BMVAL(etmidr5, 0, 8); /* TRACEIDSIZE, bits[21:16] indicates the trace ID width */
@@ -1182,53 +1179,53 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
state = drvdata->save_state;
state->trcprgctlr = readl(drvdata->base + TRCPRGCTLR);
state->trcprocselr = readl(drvdata->base + TRCPROCSELR);
state->trcconfigr = readl(drvdata->base + TRCCONFIGR);
state->trcauxctlr = readl(drvdata->base + TRCAUXCTLR);
state->trceventctl0r = readl(drvdata->base + TRCEVENTCTL0R);
state->trceventctl1r = readl(drvdata->base + TRCEVENTCTL1R);
state->trcstallctlr = readl(drvdata->base + TRCSTALLCTLR);
state->trctsctlr = readl(drvdata->base + TRCTSCTLR);
state->trcsyncpr = readl(drvdata->base + TRCSYNCPR);
state->trcccctlr = readl(drvdata->base + TRCCCCTLR);
state->trcbbctlr = readl(drvdata->base + TRCBBCTLR);
state->trctraceidr = readl(drvdata->base + TRCTRACEIDR);
state->trcqctlr = readl(drvdata->base + TRCQCTLR);
state->trcvictlr = readl(drvdata->base + TRCVICTLR);
state->trcviiectlr = readl(drvdata->base + TRCVIIECTLR);
state->trcvissctlr = readl(drvdata->base + TRCVISSCTLR);
state->trcvipcssctlr = readl(drvdata->base + TRCVIPCSSCTLR);
state->trcvdctlr = readl(drvdata->base + TRCVDCTLR);
state->trcvdsacctlr = readl(drvdata->base + TRCVDSACCTLR);
state->trcvdarcctlr = readl(drvdata->base + TRCVDARCCTLR);
state->trcprgctlr = etm4x_read32(csa, TRCPRGCTLR);
state->trcprocselr = etm4x_read32(csa, TRCPROCSELR);
state->trcconfigr = etm4x_read32(csa, TRCCONFIGR);
state->trcauxctlr = etm4x_read32(csa, TRCAUXCTLR);
state->trceventctl0r = etm4x_read32(csa, TRCEVENTCTL0R);
state->trceventctl1r = etm4x_read32(csa, TRCEVENTCTL1R);
state->trcstallctlr = etm4x_read32(csa, TRCSTALLCTLR);
state->trctsctlr = etm4x_read32(csa, TRCTSCTLR);
state->trcsyncpr = etm4x_read32(csa, TRCSYNCPR);
state->trcccctlr = etm4x_read32(csa, TRCCCCTLR);
state->trcbbctlr = etm4x_read32(csa, TRCBBCTLR);
state->trctraceidr = etm4x_read32(csa, TRCTRACEIDR);
state->trcqctlr = etm4x_read32(csa, TRCQCTLR);
state->trcvictlr = etm4x_read32(csa, TRCVICTLR);
state->trcviiectlr = etm4x_read32(csa, TRCVIIECTLR);
state->trcvissctlr = etm4x_read32(csa, TRCVISSCTLR);
state->trcvipcssctlr = etm4x_read32(csa, TRCVIPCSSCTLR);
state->trcvdctlr = etm4x_read32(csa, TRCVDCTLR);
state->trcvdsacctlr = etm4x_read32(csa, TRCVDSACCTLR);
state->trcvdarcctlr = etm4x_read32(csa, TRCVDARCCTLR); for (i = 0; i < drvdata->nrseqstate - 1; i++)
state->trcseqevr[i] = readl(drvdata->base + TRCSEQEVRn(i));
state->trcseqevr[i] = etm4x_read32(csa, TRCSEQEVRn(i));
state->trcseqrstevr = readl(drvdata->base + TRCSEQRSTEVR);
state->trcseqstr = readl(drvdata->base + TRCSEQSTR);
state->trcextinselr = readl(drvdata->base + TRCEXTINSELR);
state->trcseqrstevr = etm4x_read32(csa, TRCSEQRSTEVR);
state->trcseqstr = etm4x_read32(csa, TRCSEQSTR);
state->trcextinselr = etm4x_read32(csa, TRCEXTINSELR); for (i = 0; i < drvdata->nr_cntr; i++) {
state->trccntrldvr[i] = readl(drvdata->base + TRCCNTRLDVRn(i));
state->trccntctlr[i] = readl(drvdata->base + TRCCNTCTLRn(i));
state->trccntvr[i] = readl(drvdata->base + TRCCNTVRn(i));
state->trccntrldvr[i] = etm4x_read32(csa, TRCCNTRLDVRn(i));
state->trccntctlr[i] = etm4x_read32(csa, TRCCNTCTLRn(i));
state->trccntvr[i] = etm4x_read32(csa, TRCCNTVRn(i)); } for (i = 0; i < drvdata->nr_resource * 2; i++)
state->trcrsctlr[i] = readl(drvdata->base + TRCRSCTLRn(i));
state->trcrsctlr[i] = etm4x_read32(csa, TRCRSCTLRn(i)); for (i = 0; i < drvdata->nr_ss_cmp; i++) {
state->trcssccr[i] = readl(drvdata->base + TRCSSCCRn(i));
state->trcsscsr[i] = readl(drvdata->base + TRCSSCSRn(i));
state->trcsspcicr[i] = readl(drvdata->base + TRCSSPCICRn(i));
state->trcssccr[i] = etm4x_read32(csa, TRCSSCCRn(i));
state->trcsscsr[i] = etm4x_read32(csa, TRCSSCSRn(i));
state->trcsspcicr[i] = etm4x_read32(csa, TRCSSPCICRn(i)); } for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
state->trcacvr[i] = readq(drvdata->base + TRCACVRn(i));
state->trcacatr[i] = readq(drvdata->base + TRCACATRn(i));
state->trcacvr[i] = etm4x_read64(csa, TRCACVRn(i));
state->trcacatr[i] = etm4x_read64(csa, TRCACATRn(i)); } /*
@@ -1239,20 +1236,20 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) */
for (i = 0; i < drvdata->numcidc; i++)
state->trccidcvr[i] = readq(drvdata->base + TRCCIDCVRn(i));
state->trccidcvr[i] = etm4x_read64(csa, TRCCIDCVRn(i)); for (i = 0; i < drvdata->numvmidc; i++)
state->trcvmidcvr[i] = readq(drvdata->base + TRCVMIDCVRn(i));
state->trcvmidcvr[i] = etm4x_read64(csa, TRCVMIDCVRn(i));
state->trccidcctlr0 = readl(drvdata->base + TRCCIDCCTLR0);
state->trccidcctlr1 = readl(drvdata->base + TRCCIDCCTLR1);
state->trccidcctlr0 = etm4x_read32(csa, TRCCIDCCTLR0);
state->trccidcctlr1 = etm4x_read32(csa, TRCCIDCCTLR1);
state->trcvmidcctlr0 = readl(drvdata->base + TRCVMIDCCTLR0);
state->trcvmidcctlr0 = readl(drvdata->base + TRCVMIDCCTLR1);
state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR0);
state->trcvmidcctlr0 = etm4x_read32(csa, TRCVMIDCCTLR1);
state->trcclaimset = readl(drvdata->base + TRCCLAIMCLR);
state->trcclaimset = etm4x_read32(csa, TRCCLAIMCLR);
state->trcpdcr = readl(drvdata->base + TRCPDCR);
state->trcpdcr = etm4x_read32(csa, TRCPDCR); /* wait for TRCSTATR.IDLE to go up */ if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 1)) {
@@ -1270,8 +1267,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) * potentially save power on systems that respect the TRCPDCR_PU * despite requesting software to save/restore state. */
writel_relaxed((state->trcpdcr & ~TRCPDCR_PU),
drvdata->base + TRCPDCR);
etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU), TRCPDCR);
out: CS_LOCK(csa); @@ -1291,84 +1287,72 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) csa = &csdev->access; CS_UNLOCK(csa);
writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
writel_relaxed(state->trcprgctlr, drvdata->base + TRCPRGCTLR);
writel_relaxed(state->trcprocselr, drvdata->base + TRCPROCSELR);
writel_relaxed(state->trcconfigr, drvdata->base + TRCCONFIGR);
writel_relaxed(state->trcauxctlr, drvdata->base + TRCAUXCTLR);
writel_relaxed(state->trceventctl0r, drvdata->base + TRCEVENTCTL0R);
writel_relaxed(state->trceventctl1r, drvdata->base + TRCEVENTCTL1R);
writel_relaxed(state->trcstallctlr, drvdata->base + TRCSTALLCTLR);
writel_relaxed(state->trctsctlr, drvdata->base + TRCTSCTLR);
writel_relaxed(state->trcsyncpr, drvdata->base + TRCSYNCPR);
writel_relaxed(state->trcccctlr, drvdata->base + TRCCCCTLR);
writel_relaxed(state->trcbbctlr, drvdata->base + TRCBBCTLR);
writel_relaxed(state->trctraceidr, drvdata->base + TRCTRACEIDR);
writel_relaxed(state->trcqctlr, drvdata->base + TRCQCTLR);
writel_relaxed(state->trcvictlr, drvdata->base + TRCVICTLR);
writel_relaxed(state->trcviiectlr, drvdata->base + TRCVIIECTLR);
writel_relaxed(state->trcvissctlr, drvdata->base + TRCVISSCTLR);
writel_relaxed(state->trcvipcssctlr, drvdata->base + TRCVIPCSSCTLR);
writel_relaxed(state->trcvdctlr, drvdata->base + TRCVDCTLR);
writel_relaxed(state->trcvdsacctlr, drvdata->base + TRCVDSACCTLR);
writel_relaxed(state->trcvdarcctlr, drvdata->base + TRCVDARCCTLR);
etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
etm4x_relaxed_write32(csa, state->trcprgctlr, TRCPRGCTLR);
etm4x_relaxed_write32(csa, state->trcprocselr, TRCPROCSELR);
etm4x_relaxed_write32(csa, state->trcconfigr, TRCCONFIGR);
etm4x_relaxed_write32(csa, state->trcauxctlr, TRCAUXCTLR);
etm4x_relaxed_write32(csa, state->trceventctl0r, TRCEVENTCTL0R);
etm4x_relaxed_write32(csa, state->trceventctl1r, TRCEVENTCTL1R);
etm4x_relaxed_write32(csa, state->trcstallctlr, TRCSTALLCTLR);
etm4x_relaxed_write32(csa, state->trctsctlr, TRCTSCTLR);
etm4x_relaxed_write32(csa, state->trcsyncpr, TRCSYNCPR);
etm4x_relaxed_write32(csa, state->trcccctlr, TRCCCCTLR);
etm4x_relaxed_write32(csa, state->trcbbctlr, TRCBBCTLR);
etm4x_relaxed_write32(csa, state->trctraceidr, TRCTRACEIDR);
etm4x_relaxed_write32(csa, state->trcqctlr, TRCQCTLR);
etm4x_relaxed_write32(csa, state->trcvictlr, TRCVICTLR);
etm4x_relaxed_write32(csa, state->trcviiectlr, TRCVIIECTLR);
etm4x_relaxed_write32(csa, state->trcvissctlr, TRCVISSCTLR);
etm4x_relaxed_write32(csa, state->trcvipcssctlr, TRCVIPCSSCTLR);
etm4x_relaxed_write32(csa, state->trcvdctlr, TRCVDCTLR);
etm4x_relaxed_write32(csa, state->trcvdsacctlr, TRCVDSACCTLR);
etm4x_relaxed_write32(csa, state->trcvdarcctlr, TRCVDARCCTLR); for (i = 0; i < drvdata->nrseqstate - 1; i++)
writel_relaxed(state->trcseqevr[i],
drvdata->base + TRCSEQEVRn(i));
etm4x_relaxed_write32(csa, state->trcseqevr[i], TRCSEQEVRn(i));
writel_relaxed(state->trcseqrstevr, drvdata->base + TRCSEQRSTEVR);
writel_relaxed(state->trcseqstr, drvdata->base + TRCSEQSTR);
writel_relaxed(state->trcextinselr, drvdata->base + TRCEXTINSELR);
etm4x_relaxed_write32(csa, state->trcseqrstevr, TRCSEQRSTEVR);
etm4x_relaxed_write32(csa, state->trcseqstr, TRCSEQSTR);
etm4x_relaxed_write32(csa, state->trcextinselr, TRCEXTINSELR); for (i = 0; i < drvdata->nr_cntr; i++) {
writel_relaxed(state->trccntrldvr[i],
drvdata->base + TRCCNTRLDVRn(i));
writel_relaxed(state->trccntctlr[i],
drvdata->base + TRCCNTCTLRn(i));
writel_relaxed(state->trccntvr[i],
drvdata->base + TRCCNTVRn(i));
etm4x_relaxed_write32(csa, state->trccntrldvr[i], TRCCNTRLDVRn(i));
etm4x_relaxed_write32(csa, state->trccntctlr[i], TRCCNTCTLRn(i));
etm4x_relaxed_write32(csa, state->trccntvr[i], TRCCNTVRn(i)); } for (i = 0; i < drvdata->nr_resource * 2; i++)
writel_relaxed(state->trcrsctlr[i],
drvdata->base + TRCRSCTLRn(i));
etm4x_relaxed_write32(csa, state->trcrsctlr[i], TRCRSCTLRn(i)); for (i = 0; i < drvdata->nr_ss_cmp; i++) {
writel_relaxed(state->trcssccr[i],
drvdata->base + TRCSSCCRn(i));
writel_relaxed(state->trcsscsr[i],
drvdata->base + TRCSSCSRn(i));
writel_relaxed(state->trcsspcicr[i],
drvdata->base + TRCSSPCICRn(i));
etm4x_relaxed_write32(csa, state->trcssccr[i], TRCSSCCRn(i));
etm4x_relaxed_write32(csa, state->trcsscsr[i], TRCSSCSRn(i));
etm4x_relaxed_write32(csa, state->trcsspcicr[i], TRCSSPCICRn(i)); } for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
writeq_relaxed(state->trcacvr[i],
drvdata->base + TRCACVRn(i));
writeq_relaxed(state->trcacatr[i],
drvdata->base + TRCACATRn(i));
etm4x_relaxed_write64(csa, state->trcacvr[i], TRCACVRn(i));
etm4x_relaxed_write64(csa, state->trcacatr[i], TRCACATRn(i)); } for (i = 0; i < drvdata->numcidc; i++)
writeq_relaxed(state->trccidcvr[i],
drvdata->base + TRCCIDCVRn(i));
etm4x_relaxed_write64(csa, state->trccidcvr[i], TRCCIDCVRn(i)); for (i = 0; i < drvdata->numvmidc; i++)
writeq_relaxed(state->trcvmidcvr[i],
drvdata->base + TRCVMIDCVRn(i));
etm4x_relaxed_write64(csa, state->trcvmidcvr[i], TRCVMIDCVRn(i));
writel_relaxed(state->trccidcctlr0, drvdata->base + TRCCIDCCTLR0);
writel_relaxed(state->trccidcctlr1, drvdata->base + TRCCIDCCTLR1);
etm4x_relaxed_write32(csa, state->trccidcctlr0, TRCCIDCCTLR0);
etm4x_relaxed_write32(csa, state->trccidcctlr1, TRCCIDCCTLR1);
writel_relaxed(state->trcvmidcctlr0, drvdata->base + TRCVMIDCCTLR0);
writel_relaxed(state->trcvmidcctlr0, drvdata->base + TRCVMIDCCTLR1);
etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR0);
etm4x_relaxed_write32(csa, state->trcvmidcctlr0, TRCVMIDCCTLR1);
writel_relaxed(state->trcclaimset, drvdata->base + TRCCLAIMSET);
etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
writel_relaxed(state->trcpdcr, drvdata->base + TRCPDCR);
etm4x_relaxed_write32(csa, state->trcpdcr, TRCPDCR); drvdata->state_needs_restore = false;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 5259f96fd28a..2746d3b591ca 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -120,6 +120,30 @@ #define TRCCIDR2 0xFF8 #define TRCCIDR3 0xFFC
+#define etm4x_relaxed_read32(csa, offset) \
readl_relaxed((csa)->base + (offset))
+#define etm4x_read32(csa, offset) \
readl((csa)->base + (offset))
+#define etm4x_relaxed_write32(csa, val, offset) \
writel_relaxed((val), (csa)->base + (offset))
+#define etm4x_write32(csa, val, offset) \
writel((val), (csa)->base + (offset))
+#define etm4x_relaxed_read64(csa, offset) \
readq_relaxed((csa)->base + (offset))
+#define etm4x_read64(csa, offset) \
readq((csa)->base + (offset))
+#define etm4x_relaxed_write64(csa, val, offset) \
writeq_relaxed((val), (csa)->base + (offset))
+#define etm4x_write64(csa, val, offset) \
writeq((val), (csa)->base + (offset))
/* ETMv4 resources */ #define ETM_MAX_NR_PE 8
#define ETMv4_MAX_CNTR 4
2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
As we are about define a switch..case table for individual register access by offset for implementing the system instruction support, document the possible set of registers for each group to make it easier to co-relate.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.h | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 2746d3b591ca..c56ffec5d87e 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -44,13 +44,13 @@ #define TRCVDSACCTLR 0x0A4 #define TRCVDARCCTLR 0x0A8 /* Derived resources registers */ -#define TRCSEQEVRn(n) (0x100 + (n * 4)) +#define TRCSEQEVRn(n) (0x100 + (n * 4)) /* n = 0-2 */ #define TRCSEQRSTEVR 0x118 #define TRCSEQSTR 0x11C #define TRCEXTINSELR 0x120 -#define TRCCNTRLDVRn(n) (0x140 + (n * 4)) -#define TRCCNTCTLRn(n) (0x150 + (n * 4)) -#define TRCCNTVRn(n) (0x160 + (n * 4)) +#define TRCCNTRLDVRn(n) (0x140 + (n * 4)) /* n = 0-3 */ +#define TRCCNTCTLRn(n) (0x150 + (n * 4)) /* n = 0-3 */ +#define TRCCNTVRn(n) (0x160 + (n * 4)) /* n = 0-3 */ /* ID registers */ #define TRCIDR8 0x180 #define TRCIDR9 0x184 @@ -59,7 +59,7 @@ #define TRCIDR12 0x190 #define TRCIDR13 0x194 #define TRCIMSPEC0 0x1C0 -#define TRCIMSPECn(n) (0x1C0 + (n * 4)) +#define TRCIMSPECn(n) (0x1C0 + (n * 4)) /* n = 1-7 */ #define TRCIDR0 0x1E0 #define TRCIDR1 0x1E4 #define TRCIDR2 0x1E8 @@ -68,9 +68,12 @@ #define TRCIDR5 0x1F4 #define TRCIDR6 0x1F8 #define TRCIDR7 0x1FC -/* Resource selection registers */ +/* + * Resource selection registers, n = 2-31. + * First pair (regs 0, 1) is always present and is reserved. + */ #define TRCRSCTLRn(n) (0x200 + (n * 4)) -/* Single-shot comparator registers */ +/* Single-shot comparator registers, n = 0-7 */ #define TRCSSCCRn(n) (0x280 + (n * 4)) #define TRCSSCSRn(n) (0x2A0 + (n * 4)) #define TRCSSPCICRn(n) (0x2C0 + (n * 4)) @@ -80,11 +83,13 @@ #define TRCPDCR 0x310 #define TRCPDSR 0x314 /* Trace registers (0x318-0xEFC) */ -/* Comparator registers */ +/* Address Comparator registers n = 0-15 */ #define TRCACVRn(n) (0x400 + (n * 8)) #define TRCACATRn(n) (0x480 + (n * 8)) +/* Data Value Comparator Value registers, n = 0-7 */ #define TRCDVCVRn(n) (0x500 + (n * 16)) #define TRCDVCMRn(n) (0x580 + (n * 16)) +/* ContextID/Virtual ContextID comparators, n = 0-7 */ #define TRCCIDCVRn(n) (0x600 + (n * 8)) #define TRCVMIDCVRn(n) (0x640 + (n * 8)) #define TRCCIDCCTLR0 0x680
Reviewed-by: Mike Leach mike.leach@linaro.org
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
As we are about define a switch..case table for individual register access by offset for implementing the system instruction support, document the possible set of registers for each group to make it easier to co-relate.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.h | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 2746d3b591ca..c56ffec5d87e 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -44,13 +44,13 @@ #define TRCVDSACCTLR 0x0A4 #define TRCVDARCCTLR 0x0A8 /* Derived resources registers */ -#define TRCSEQEVRn(n) (0x100 + (n * 4)) +#define TRCSEQEVRn(n) (0x100 + (n * 4)) /* n = 0-2 */ #define TRCSEQRSTEVR 0x118 #define TRCSEQSTR 0x11C #define TRCEXTINSELR 0x120 -#define TRCCNTRLDVRn(n) (0x140 + (n * 4)) -#define TRCCNTCTLRn(n) (0x150 + (n * 4)) -#define TRCCNTVRn(n) (0x160 + (n * 4)) +#define TRCCNTRLDVRn(n) (0x140 + (n * 4)) /* n = 0-3 */ +#define TRCCNTCTLRn(n) (0x150 + (n * 4)) /* n = 0-3 */ +#define TRCCNTVRn(n) (0x160 + (n * 4)) /* n = 0-3 */ /* ID registers */ #define TRCIDR8 0x180 #define TRCIDR9 0x184 @@ -59,7 +59,7 @@ #define TRCIDR12 0x190 #define TRCIDR13 0x194 #define TRCIMSPEC0 0x1C0 -#define TRCIMSPECn(n) (0x1C0 + (n * 4)) +#define TRCIMSPECn(n) (0x1C0 + (n * 4)) /* n = 1-7 */ #define TRCIDR0 0x1E0 #define TRCIDR1 0x1E4 #define TRCIDR2 0x1E8 @@ -68,9 +68,12 @@ #define TRCIDR5 0x1F4 #define TRCIDR6 0x1F8 #define TRCIDR7 0x1FC -/* Resource selection registers */ +/*
- Resource selection registers, n = 2-31.
- First pair (regs 0, 1) is always present and is reserved.
- */
#define TRCRSCTLRn(n) (0x200 + (n * 4)) -/* Single-shot comparator registers */ +/* Single-shot comparator registers, n = 0-7 */ #define TRCSSCCRn(n) (0x280 + (n * 4)) #define TRCSSCSRn(n) (0x2A0 + (n * 4)) #define TRCSSPCICRn(n) (0x2C0 + (n * 4)) @@ -80,11 +83,13 @@ #define TRCPDCR 0x310 #define TRCPDSR 0x314 /* Trace registers (0x318-0xEFC) */ -/* Comparator registers */ +/* Address Comparator registers n = 0-15 */ #define TRCACVRn(n) (0x400 + (n * 8)) #define TRCACATRn(n) (0x480 + (n * 8)) +/* Data Value Comparator Value registers, n = 0-7 */ #define TRCDVCVRn(n) (0x500 + (n * 16)) #define TRCDVCMRn(n) (0x580 + (n * 16)) +/* ContextID/Virtual ContextID comparators, n = 0-7 */ #define TRCCIDCVRn(n) (0x600 + (n * 8)) #define TRCVMIDCVRn(n) (0x640 + (n * 8))
#define TRCCIDCCTLR0 0x680
2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
ETMv4.4 architecture defines the system instructions for accessing ETM via register accesses. Add basic support for accessing a given register via system instructions.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.c | 39 ++ drivers/hwtracing/coresight/coresight-etm4x.h | 348 ++++++++++++++++-- 2 files changed, 365 insertions(+), 22 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index f942f826d7b8..40f8113191e0 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -56,6 +56,45 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
static enum cpuhp_state hp_online;
+u64 etm4x_sysreg_read(struct csdev_access *csa, + u32 offset, + bool _relaxed, + bool _64bit) +{ + u64 res = 0; + + switch (offset) { + ETM4x_READ_CASES(res) + default : + WARN_ONCE(1, "etm4x: trying to read unsupported register @%x\n", + offset); + } + + if (!_relaxed) + __iormb(res); /* Imitate the !relaxed I/O helpers */ + + return res; +} + +void etm4x_sysreg_write(struct csdev_access *csa, + u64 val, + u32 offset, + bool _relaxed, + bool _64bit) +{ + if (!_relaxed) + __iowmb(); /* Imitate the !relaxed I/O helpers */ + if (!_64bit) + val &= GENMASK(31, 0); + + switch (offset) { + ETM4x_WRITE_CASES(val) + default : + WARN_ONCE(1, "etm4x: trying to write to unsupported register @%x\n", + offset); + } +} + static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { /* Writing 0 to TRCOSLAR unlocks the trace registers */ diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index c56ffec5d87e..4044676d2385 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -125,29 +125,323 @@ #define TRCCIDR2 0xFF8 #define TRCCIDR3 0xFFC
-#define etm4x_relaxed_read32(csa, offset) \ - readl_relaxed((csa)->base + (offset)) - -#define etm4x_read32(csa, offset) \ - readl((csa)->base + (offset)) - -#define etm4x_relaxed_write32(csa, val, offset) \ - writel_relaxed((val), (csa)->base + (offset)) - -#define etm4x_write32(csa, val, offset) \ - writel((val), (csa)->base + (offset)) - -#define etm4x_relaxed_read64(csa, offset) \ - readq_relaxed((csa)->base + (offset)) - -#define etm4x_read64(csa, offset) \ - readq((csa)->base + (offset)) - -#define etm4x_relaxed_write64(csa, val, offset) \ - writeq_relaxed((val), (csa)->base + (offset)) +/* + * System instructions to access ETM registers. + * See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions + */ +#define ETM4x_OFFSET_TO_REG(x) ((x) >> 2) + +#define ETM4x_CRn(n) (((n) >> 7) & 0x7) +#define ETM4x_Op2(n) (((n) >> 4) & 0x7) +#define ETM4x_CRm(n) ((n) & 0xf) + +#include <asm/sysreg.h> +#define ETM4x_REG_NUM_TO_SYSREG(n) \ + sys_reg(2, 1, ETM4x_CRn(n), ETM4x_CRm(n), ETM4x_Op2(n)) + +#define READ_ETM4x_REG(reg) \ + read_sysreg_s(ETM4x_REG_NUM_TO_SYSREG((reg))) +#define WRITE_ETM4x_REG(val, reg) \ + write_sysreg_s(val, ETM4x_REG_NUM_TO_SYSREG((reg))) + +#define read_etm4x_sysreg_const_offset(offset) \ + READ_ETM4x_REG(ETM4x_OFFSET_TO_REG(offset)) + +#define write_etm4x_sysreg_const_offset(val, offset) \ + WRITE_ETM4x_REG(val, ETM4x_OFFSET_TO_REG(offset)) + +#define CASE_READ(res, x) \ + case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; } + +#define CASE_WRITE(val, x) \ + case (x): { write_etm4x_sysreg_const_offset((val), (x)); break; } + +#define CASE_LIST(op, val) \ + CASE_##op((val), TRCPRGCTLR) \ + CASE_##op((val), TRCPROCSELR) \ + CASE_##op((val), TRCSTATR) \ + CASE_##op((val), TRCCONFIGR) \ + CASE_##op((val), TRCAUXCTLR) \ + CASE_##op((val), TRCEVENTCTL0R) \ + CASE_##op((val), TRCEVENTCTL1R) \ + CASE_##op((val), TRCSTALLCTLR) \ + CASE_##op((val), TRCTSCTLR) \ + CASE_##op((val), TRCSYNCPR) \ + CASE_##op((val), TRCCCCTLR) \ + CASE_##op((val), TRCBBCTLR) \ + CASE_##op((val), TRCTRACEIDR) \ + CASE_##op((val), TRCQCTLR) \ + CASE_##op((val), TRCVICTLR) \ + CASE_##op((val), TRCVIIECTLR) \ + CASE_##op((val), TRCVISSCTLR) \ + CASE_##op((val), TRCVIPCSSCTLR) \ + CASE_##op((val), TRCVDCTLR) \ + CASE_##op((val), TRCVDSACCTLR) \ + CASE_##op((val), TRCVDARCCTLR) \ + CASE_##op((val), TRCSEQEVRn(0)) \ + CASE_##op((val), TRCSEQEVRn(1)) \ + CASE_##op((val), TRCSEQEVRn(2)) \ + CASE_##op((val), TRCSEQRSTEVR) \ + CASE_##op((val), TRCSEQSTR) \ + CASE_##op((val), TRCEXTINSELR) \ + CASE_##op((val), TRCCNTRLDVRn(0)) \ + CASE_##op((val), TRCCNTRLDVRn(1)) \ + CASE_##op((val), TRCCNTRLDVRn(2)) \ + CASE_##op((val), TRCCNTRLDVRn(3)) \ + CASE_##op((val), TRCCNTCTLRn(0)) \ + CASE_##op((val), TRCCNTCTLRn(1)) \ + CASE_##op((val), TRCCNTCTLRn(2)) \ + CASE_##op((val), TRCCNTCTLRn(3)) \ + CASE_##op((val), TRCCNTVRn(0)) \ + CASE_##op((val), TRCCNTVRn(1)) \ + CASE_##op((val), TRCCNTVRn(2)) \ + CASE_##op((val), TRCCNTVRn(3)) \ + CASE_##op((val), TRCIDR8) \ + CASE_##op((val), TRCIDR9) \ + CASE_##op((val), TRCIDR10) \ + CASE_##op((val), TRCIDR11) \ + CASE_##op((val), TRCIDR12) \ + CASE_##op((val), TRCIDR13) \ + CASE_##op((val), TRCIMSPECn(0)) \ + CASE_##op((val), TRCIMSPECn(1)) \ + CASE_##op((val), TRCIMSPECn(2)) \ + CASE_##op((val), TRCIMSPECn(3)) \ + CASE_##op((val), TRCIMSPECn(4)) \ + CASE_##op((val), TRCIMSPECn(5)) \ + CASE_##op((val), TRCIMSPECn(6)) \ + CASE_##op((val), TRCIMSPECn(7)) \ + CASE_##op((val), TRCIDR0) \ + CASE_##op((val), TRCIDR1) \ + CASE_##op((val), TRCIDR2) \ + CASE_##op((val), TRCIDR3) \ + CASE_##op((val), TRCIDR4) \ + CASE_##op((val), TRCIDR5) \ + CASE_##op((val), TRCIDR6) \ + CASE_##op((val), TRCIDR7) \ + CASE_##op((val), TRCRSCTLRn(2)) \ + CASE_##op((val), TRCRSCTLRn(3)) \ + CASE_##op((val), TRCRSCTLRn(4)) \ + CASE_##op((val), TRCRSCTLRn(5)) \ + CASE_##op((val), TRCRSCTLRn(6)) \ + CASE_##op((val), TRCRSCTLRn(7)) \ + CASE_##op((val), TRCRSCTLRn(8)) \ + CASE_##op((val), TRCRSCTLRn(9)) \ + CASE_##op((val), TRCRSCTLRn(10)) \ + CASE_##op((val), TRCRSCTLRn(11)) \ + CASE_##op((val), TRCRSCTLRn(12)) \ + CASE_##op((val), TRCRSCTLRn(13)) \ + CASE_##op((val), TRCRSCTLRn(14)) \ + CASE_##op((val), TRCRSCTLRn(15)) \ + CASE_##op((val), TRCRSCTLRn(16)) \ + CASE_##op((val), TRCRSCTLRn(17)) \ + CASE_##op((val), TRCRSCTLRn(18)) \ + CASE_##op((val), TRCRSCTLRn(19)) \ + CASE_##op((val), TRCRSCTLRn(20)) \ + CASE_##op((val), TRCRSCTLRn(21)) \ + CASE_##op((val), TRCRSCTLRn(22)) \ + CASE_##op((val), TRCRSCTLRn(23)) \ + CASE_##op((val), TRCRSCTLRn(24)) \ + CASE_##op((val), TRCRSCTLRn(25)) \ + CASE_##op((val), TRCRSCTLRn(26)) \ + CASE_##op((val), TRCRSCTLRn(27)) \ + CASE_##op((val), TRCRSCTLRn(28)) \ + CASE_##op((val), TRCRSCTLRn(29)) \ + CASE_##op((val), TRCRSCTLRn(30)) \ + CASE_##op((val), TRCRSCTLRn(31)) \ + CASE_##op((val), TRCSSCCRn(0)) \ + CASE_##op((val), TRCSSCCRn(1)) \ + CASE_##op((val), TRCSSCCRn(2)) \ + CASE_##op((val), TRCSSCCRn(3)) \ + CASE_##op((val), TRCSSCCRn(4)) \ + CASE_##op((val), TRCSSCCRn(5)) \ + CASE_##op((val), TRCSSCCRn(6)) \ + CASE_##op((val), TRCSSCCRn(7)) \ + CASE_##op((val), TRCSSCSRn(0)) \ + CASE_##op((val), TRCSSCSRn(1)) \ + CASE_##op((val), TRCSSCSRn(2)) \ + CASE_##op((val), TRCSSCSRn(3)) \ + CASE_##op((val), TRCSSCSRn(4)) \ + CASE_##op((val), TRCSSCSRn(5)) \ + CASE_##op((val), TRCSSCSRn(6)) \ + CASE_##op((val), TRCSSCSRn(7)) \ + CASE_##op((val), TRCSSPCICRn(0)) \ + CASE_##op((val), TRCSSPCICRn(1)) \ + CASE_##op((val), TRCSSPCICRn(2)) \ + CASE_##op((val), TRCSSPCICRn(3)) \ + CASE_##op((val), TRCSSPCICRn(4)) \ + CASE_##op((val), TRCSSPCICRn(5)) \ + CASE_##op((val), TRCSSPCICRn(6)) \ + CASE_##op((val), TRCSSPCICRn(7)) \ + CASE_##op((val), TRCOSLAR) \ + CASE_##op((val), TRCOSLSR) \ + CASE_##op((val), TRCPDCR) \ + CASE_##op((val), TRCPDSR) \ + CASE_##op((val), TRCACVRn(0)) \ + CASE_##op((val), TRCACVRn(1)) \ + CASE_##op((val), TRCACVRn(2)) \ + CASE_##op((val), TRCACVRn(3)) \ + CASE_##op((val), TRCACVRn(4)) \ + CASE_##op((val), TRCACVRn(5)) \ + CASE_##op((val), TRCACVRn(6)) \ + CASE_##op((val), TRCACVRn(7)) \ + CASE_##op((val), TRCACVRn(8)) \ + CASE_##op((val), TRCACVRn(9)) \ + CASE_##op((val), TRCACVRn(10)) \ + CASE_##op((val), TRCACVRn(11)) \ + CASE_##op((val), TRCACVRn(12)) \ + CASE_##op((val), TRCACVRn(13)) \ + CASE_##op((val), TRCACVRn(14)) \ + CASE_##op((val), TRCACVRn(15)) \ + CASE_##op((val), TRCACATRn(0)) \ + CASE_##op((val), TRCACATRn(1)) \ + CASE_##op((val), TRCACATRn(2)) \ + CASE_##op((val), TRCACATRn(3)) \ + CASE_##op((val), TRCACATRn(4)) \ + CASE_##op((val), TRCACATRn(5)) \ + CASE_##op((val), TRCACATRn(6)) \ + CASE_##op((val), TRCACATRn(7)) \ + CASE_##op((val), TRCACATRn(8)) \ + CASE_##op((val), TRCACATRn(9)) \ + CASE_##op((val), TRCACATRn(10)) \ + CASE_##op((val), TRCACATRn(11)) \ + CASE_##op((val), TRCACATRn(12)) \ + CASE_##op((val), TRCACATRn(13)) \ + CASE_##op((val), TRCACATRn(14)) \ + CASE_##op((val), TRCACATRn(15)) \ + CASE_##op((val), TRCDVCVRn(0)) \ + CASE_##op((val), TRCDVCVRn(1)) \ + CASE_##op((val), TRCDVCVRn(2)) \ + CASE_##op((val), TRCDVCVRn(3)) \ + CASE_##op((val), TRCDVCVRn(4)) \ + CASE_##op((val), TRCDVCVRn(5)) \ + CASE_##op((val), TRCDVCVRn(6)) \ + CASE_##op((val), TRCDVCVRn(7)) \ + CASE_##op((val), TRCDVCMRn(0)) \ + CASE_##op((val), TRCDVCMRn(1)) \ + CASE_##op((val), TRCDVCMRn(2)) \ + CASE_##op((val), TRCDVCMRn(3)) \ + CASE_##op((val), TRCDVCMRn(4)) \ + CASE_##op((val), TRCDVCMRn(5)) \ + CASE_##op((val), TRCDVCMRn(6)) \ + CASE_##op((val), TRCDVCMRn(7)) \ + CASE_##op((val), TRCCIDCVRn(0)) \ + CASE_##op((val), TRCCIDCVRn(1)) \ + CASE_##op((val), TRCCIDCVRn(2)) \ + CASE_##op((val), TRCCIDCVRn(3)) \ + CASE_##op((val), TRCCIDCVRn(4)) \ + CASE_##op((val), TRCCIDCVRn(5)) \ + CASE_##op((val), TRCCIDCVRn(6)) \ + CASE_##op((val), TRCCIDCVRn(7)) \ + CASE_##op((val), TRCVMIDCVRn(0)) \ + CASE_##op((val), TRCVMIDCVRn(1)) \ + CASE_##op((val), TRCVMIDCVRn(2)) \ + CASE_##op((val), TRCVMIDCVRn(3)) \ + CASE_##op((val), TRCVMIDCVRn(4)) \ + CASE_##op((val), TRCVMIDCVRn(5)) \ + CASE_##op((val), TRCVMIDCVRn(6)) \ + CASE_##op((val), TRCVMIDCVRn(7)) \ + CASE_##op((val), TRCCIDCCTLR0) \ + CASE_##op((val), TRCCIDCCTLR1) \ + CASE_##op((val), TRCVMIDCCTLR0) \ + CASE_##op((val), TRCVMIDCCTLR1) \ + CASE_##op((val), TRCITCTRL) \ + CASE_##op((val), TRCCLAIMSET) \ + CASE_##op((val), TRCCLAIMCLR) \ + CASE_##op((val), TRCDEVAFF0) \ + CASE_##op((val), TRCDEVAFF1) \ + CASE_##op((val), TRCLAR) \ + CASE_##op((val), TRCLSR) \ + CASE_##op((val), TRCAUTHSTATUS) \ + CASE_##op((val), TRCDEVARCH) \ + CASE_##op((val), TRCDEVID) \ + CASE_##op((val), TRCDEVTYPE) \ + CASE_##op((val), TRCPIDR4) \ + CASE_##op((val), TRCPIDR5) \ + CASE_##op((val), TRCPIDR6) \ + CASE_##op((val), TRCPIDR7) \ + CASE_##op((val), TRCPIDR0) \ + CASE_##op((val), TRCPIDR1) \ + CASE_##op((val), TRCPIDR2) \ + CASE_##op((val), TRCPIDR3) + +#define ETM4x_READ_CASES(res) CASE_LIST(READ, (res)) +#define ETM4x_WRITE_CASES(val) CASE_LIST(WRITE, (val)) + +#define read_etm4x_sysreg_offset(csa, offset, _64bit) \ + ({ \ + u64 __val; \ + \ + if (__builtin_constant_p((offset))) \ + __val = read_etm4x_sysreg_const_offset((offset)); \ + else \ + __val = etm4x_sysreg_read((csa), (offset), \ + true, _64bit); \ + __val; \ + }) + +#define write_etm4x_sysreg_offset(csa, val, offset, _64bit) \ + do { \ + if (__builtin_constant_p((offset))) \ + write_etm4x_sysreg_const_offset((val), \ + (offset)); \ + else \ + etm4x_sysreg_write((csa), (val), (offset), \ + true, _64bit); \ + } while (0) + + +#define etm4x_relaxed_read32(csa, offset) \ + (u32)((csa)->io_mem ? \ + readl_relaxed((csa)->base + (offset)) : \ + read_etm4x_sysreg_offset((csa), (offset), false)) +#define etm4x_relaxed_read64(csa, offset) \ + (u64)((csa)->io_mem ? \ + readq_relaxed((csa)->base + (offset)) : \ + read_etm4x_sysreg_offset((csa), (offset), true)) +#define etm4x_read32(csa, offset) \ + ({ \ + u32 __val = etm4x_relaxed_read32((csa), (offset)); \ + __iormb(__val); \ + __val; \ + }) + +#define etm4x_read64(csa, offset) \ + ({ \ + u64 __val = etm4x_relaxed_read64((csa), (offset)); \ + __iormb(__val); \ + __val; \ + }) + +#define etm4x_relaxed_write32(csa, val, offset) \ + do { \ + if ((csa)->io_mem) \ + writel_relaxed((val), (csa)->base + (offset)); \ + else \ + write_etm4x_sysreg_offset((csa), (val), \ + (offset), false); \ + } while (0) + +#define etm4x_relaxed_write64(csa, val, offset) \ + do { \ + if ((csa)->io_mem) \ + writeq_relaxed((val), (csa)->base + (offset)); \ + else \ + write_etm4x_sysreg_offset((csa), (val), \ + (offset), true); \ + } while (0) + +#define etm4x_write32(csa, val, offset) \ + do { \ + __iowmb(); \ + etm4x_relaxed_write32((csa), (val), (offset)); \ + } while (0) + +#define etm4x_write64(csa, val, offset) \ + do { \ + __iowmb(); \ + etm4x_relaxed_write64((csa), (val), (offset)); \ + } while (0)
-#define etm4x_write64(csa, val, offset) \ - writeq((val), (csa)->base + (offset))
/* ETMv4 resources */ #define ETM_MAX_NR_PE 8 @@ -509,4 +803,14 @@ enum etm_addr_ctxtype {
extern const struct attribute_group *coresight_etmv4_groups[]; void etm4_config_trace_mode(struct etmv4_config *config); + +u64 etm4x_sysreg_read(struct csdev_access *csa, + u32 offset, + bool _relaxed, + bool _64bit); +void etm4x_sysreg_write(struct csdev_access *csa, + u64 val, + u32 offset, + bool _relaxed, + bool _64bit); #endif
Reviewed-by: Mike Leach mike.leach@arm.com
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
ETMv4.4 architecture defines the system instructions for accessing ETM via register accesses. Add basic support for accessing a given register via system instructions.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 39 ++ drivers/hwtracing/coresight/coresight-etm4x.h | 348 ++++++++++++++++-- 2 files changed, 365 insertions(+), 22 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index f942f826d7b8..40f8113191e0 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -56,6 +56,45 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
static enum cpuhp_state hp_online;
+u64 etm4x_sysreg_read(struct csdev_access *csa,
u32 offset,
bool _relaxed,
bool _64bit)
+{
u64 res = 0;
switch (offset) {
ETM4x_READ_CASES(res)
default :
WARN_ONCE(1, "etm4x: trying to read unsupported register @%x\n",
offset);
}
if (!_relaxed)
__iormb(res); /* Imitate the !relaxed I/O helpers */
return res;
+}
+void etm4x_sysreg_write(struct csdev_access *csa,
u64 val,
u32 offset,
bool _relaxed,
bool _64bit)
+{
if (!_relaxed)
__iowmb(); /* Imitate the !relaxed I/O helpers */
if (!_64bit)
val &= GENMASK(31, 0);
switch (offset) {
ETM4x_WRITE_CASES(val)
default :
WARN_ONCE(1, "etm4x: trying to write to unsupported register @%x\n",
offset);
}
+}
static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { /* Writing 0 to TRCOSLAR unlocks the trace registers */ diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index c56ffec5d87e..4044676d2385 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -125,29 +125,323 @@ #define TRCCIDR2 0xFF8 #define TRCCIDR3 0xFFC
-#define etm4x_relaxed_read32(csa, offset) \
readl_relaxed((csa)->base + (offset))
-#define etm4x_read32(csa, offset) \
readl((csa)->base + (offset))
-#define etm4x_relaxed_write32(csa, val, offset) \
writel_relaxed((val), (csa)->base + (offset))
-#define etm4x_write32(csa, val, offset) \
writel((val), (csa)->base + (offset))
-#define etm4x_relaxed_read64(csa, offset) \
readq_relaxed((csa)->base + (offset))
-#define etm4x_read64(csa, offset) \
readq((csa)->base + (offset))
-#define etm4x_relaxed_write64(csa, val, offset) \
writeq_relaxed((val), (csa)->base + (offset))
+/*
- System instructions to access ETM registers.
- See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions
- */
+#define ETM4x_OFFSET_TO_REG(x) ((x) >> 2)
+#define ETM4x_CRn(n) (((n) >> 7) & 0x7) +#define ETM4x_Op2(n) (((n) >> 4) & 0x7) +#define ETM4x_CRm(n) ((n) & 0xf)
+#include <asm/sysreg.h> +#define ETM4x_REG_NUM_TO_SYSREG(n) \
sys_reg(2, 1, ETM4x_CRn(n), ETM4x_CRm(n), ETM4x_Op2(n))
+#define READ_ETM4x_REG(reg) \
read_sysreg_s(ETM4x_REG_NUM_TO_SYSREG((reg)))
+#define WRITE_ETM4x_REG(val, reg) \
write_sysreg_s(val, ETM4x_REG_NUM_TO_SYSREG((reg)))
+#define read_etm4x_sysreg_const_offset(offset) \
READ_ETM4x_REG(ETM4x_OFFSET_TO_REG(offset))
+#define write_etm4x_sysreg_const_offset(val, offset) \
WRITE_ETM4x_REG(val, ETM4x_OFFSET_TO_REG(offset))
+#define CASE_READ(res, x) \
case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }
+#define CASE_WRITE(val, x) \
case (x): { write_etm4x_sysreg_const_offset((val), (x)); break; }
+#define CASE_LIST(op, val) \
CASE_##op((val), TRCPRGCTLR) \
CASE_##op((val), TRCPROCSELR) \
CASE_##op((val), TRCSTATR) \
CASE_##op((val), TRCCONFIGR) \
CASE_##op((val), TRCAUXCTLR) \
CASE_##op((val), TRCEVENTCTL0R) \
CASE_##op((val), TRCEVENTCTL1R) \
CASE_##op((val), TRCSTALLCTLR) \
CASE_##op((val), TRCTSCTLR) \
CASE_##op((val), TRCSYNCPR) \
CASE_##op((val), TRCCCCTLR) \
CASE_##op((val), TRCBBCTLR) \
CASE_##op((val), TRCTRACEIDR) \
CASE_##op((val), TRCQCTLR) \
CASE_##op((val), TRCVICTLR) \
CASE_##op((val), TRCVIIECTLR) \
CASE_##op((val), TRCVISSCTLR) \
CASE_##op((val), TRCVIPCSSCTLR) \
CASE_##op((val), TRCVDCTLR) \
CASE_##op((val), TRCVDSACCTLR) \
CASE_##op((val), TRCVDARCCTLR) \
CASE_##op((val), TRCSEQEVRn(0)) \
CASE_##op((val), TRCSEQEVRn(1)) \
CASE_##op((val), TRCSEQEVRn(2)) \
CASE_##op((val), TRCSEQRSTEVR) \
CASE_##op((val), TRCSEQSTR) \
CASE_##op((val), TRCEXTINSELR) \
CASE_##op((val), TRCCNTRLDVRn(0)) \
CASE_##op((val), TRCCNTRLDVRn(1)) \
CASE_##op((val), TRCCNTRLDVRn(2)) \
CASE_##op((val), TRCCNTRLDVRn(3)) \
CASE_##op((val), TRCCNTCTLRn(0)) \
CASE_##op((val), TRCCNTCTLRn(1)) \
CASE_##op((val), TRCCNTCTLRn(2)) \
CASE_##op((val), TRCCNTCTLRn(3)) \
CASE_##op((val), TRCCNTVRn(0)) \
CASE_##op((val), TRCCNTVRn(1)) \
CASE_##op((val), TRCCNTVRn(2)) \
CASE_##op((val), TRCCNTVRn(3)) \
CASE_##op((val), TRCIDR8) \
CASE_##op((val), TRCIDR9) \
CASE_##op((val), TRCIDR10) \
CASE_##op((val), TRCIDR11) \
CASE_##op((val), TRCIDR12) \
CASE_##op((val), TRCIDR13) \
CASE_##op((val), TRCIMSPECn(0)) \
CASE_##op((val), TRCIMSPECn(1)) \
CASE_##op((val), TRCIMSPECn(2)) \
CASE_##op((val), TRCIMSPECn(3)) \
CASE_##op((val), TRCIMSPECn(4)) \
CASE_##op((val), TRCIMSPECn(5)) \
CASE_##op((val), TRCIMSPECn(6)) \
CASE_##op((val), TRCIMSPECn(7)) \
CASE_##op((val), TRCIDR0) \
CASE_##op((val), TRCIDR1) \
CASE_##op((val), TRCIDR2) \
CASE_##op((val), TRCIDR3) \
CASE_##op((val), TRCIDR4) \
CASE_##op((val), TRCIDR5) \
CASE_##op((val), TRCIDR6) \
CASE_##op((val), TRCIDR7) \
CASE_##op((val), TRCRSCTLRn(2)) \
CASE_##op((val), TRCRSCTLRn(3)) \
CASE_##op((val), TRCRSCTLRn(4)) \
CASE_##op((val), TRCRSCTLRn(5)) \
CASE_##op((val), TRCRSCTLRn(6)) \
CASE_##op((val), TRCRSCTLRn(7)) \
CASE_##op((val), TRCRSCTLRn(8)) \
CASE_##op((val), TRCRSCTLRn(9)) \
CASE_##op((val), TRCRSCTLRn(10)) \
CASE_##op((val), TRCRSCTLRn(11)) \
CASE_##op((val), TRCRSCTLRn(12)) \
CASE_##op((val), TRCRSCTLRn(13)) \
CASE_##op((val), TRCRSCTLRn(14)) \
CASE_##op((val), TRCRSCTLRn(15)) \
CASE_##op((val), TRCRSCTLRn(16)) \
CASE_##op((val), TRCRSCTLRn(17)) \
CASE_##op((val), TRCRSCTLRn(18)) \
CASE_##op((val), TRCRSCTLRn(19)) \
CASE_##op((val), TRCRSCTLRn(20)) \
CASE_##op((val), TRCRSCTLRn(21)) \
CASE_##op((val), TRCRSCTLRn(22)) \
CASE_##op((val), TRCRSCTLRn(23)) \
CASE_##op((val), TRCRSCTLRn(24)) \
CASE_##op((val), TRCRSCTLRn(25)) \
CASE_##op((val), TRCRSCTLRn(26)) \
CASE_##op((val), TRCRSCTLRn(27)) \
CASE_##op((val), TRCRSCTLRn(28)) \
CASE_##op((val), TRCRSCTLRn(29)) \
CASE_##op((val), TRCRSCTLRn(30)) \
CASE_##op((val), TRCRSCTLRn(31)) \
CASE_##op((val), TRCSSCCRn(0)) \
CASE_##op((val), TRCSSCCRn(1)) \
CASE_##op((val), TRCSSCCRn(2)) \
CASE_##op((val), TRCSSCCRn(3)) \
CASE_##op((val), TRCSSCCRn(4)) \
CASE_##op((val), TRCSSCCRn(5)) \
CASE_##op((val), TRCSSCCRn(6)) \
CASE_##op((val), TRCSSCCRn(7)) \
CASE_##op((val), TRCSSCSRn(0)) \
CASE_##op((val), TRCSSCSRn(1)) \
CASE_##op((val), TRCSSCSRn(2)) \
CASE_##op((val), TRCSSCSRn(3)) \
CASE_##op((val), TRCSSCSRn(4)) \
CASE_##op((val), TRCSSCSRn(5)) \
CASE_##op((val), TRCSSCSRn(6)) \
CASE_##op((val), TRCSSCSRn(7)) \
CASE_##op((val), TRCSSPCICRn(0)) \
CASE_##op((val), TRCSSPCICRn(1)) \
CASE_##op((val), TRCSSPCICRn(2)) \
CASE_##op((val), TRCSSPCICRn(3)) \
CASE_##op((val), TRCSSPCICRn(4)) \
CASE_##op((val), TRCSSPCICRn(5)) \
CASE_##op((val), TRCSSPCICRn(6)) \
CASE_##op((val), TRCSSPCICRn(7)) \
CASE_##op((val), TRCOSLAR) \
CASE_##op((val), TRCOSLSR) \
CASE_##op((val), TRCPDCR) \
CASE_##op((val), TRCPDSR) \
CASE_##op((val), TRCACVRn(0)) \
CASE_##op((val), TRCACVRn(1)) \
CASE_##op((val), TRCACVRn(2)) \
CASE_##op((val), TRCACVRn(3)) \
CASE_##op((val), TRCACVRn(4)) \
CASE_##op((val), TRCACVRn(5)) \
CASE_##op((val), TRCACVRn(6)) \
CASE_##op((val), TRCACVRn(7)) \
CASE_##op((val), TRCACVRn(8)) \
CASE_##op((val), TRCACVRn(9)) \
CASE_##op((val), TRCACVRn(10)) \
CASE_##op((val), TRCACVRn(11)) \
CASE_##op((val), TRCACVRn(12)) \
CASE_##op((val), TRCACVRn(13)) \
CASE_##op((val), TRCACVRn(14)) \
CASE_##op((val), TRCACVRn(15)) \
CASE_##op((val), TRCACATRn(0)) \
CASE_##op((val), TRCACATRn(1)) \
CASE_##op((val), TRCACATRn(2)) \
CASE_##op((val), TRCACATRn(3)) \
CASE_##op((val), TRCACATRn(4)) \
CASE_##op((val), TRCACATRn(5)) \
CASE_##op((val), TRCACATRn(6)) \
CASE_##op((val), TRCACATRn(7)) \
CASE_##op((val), TRCACATRn(8)) \
CASE_##op((val), TRCACATRn(9)) \
CASE_##op((val), TRCACATRn(10)) \
CASE_##op((val), TRCACATRn(11)) \
CASE_##op((val), TRCACATRn(12)) \
CASE_##op((val), TRCACATRn(13)) \
CASE_##op((val), TRCACATRn(14)) \
CASE_##op((val), TRCACATRn(15)) \
CASE_##op((val), TRCDVCVRn(0)) \
CASE_##op((val), TRCDVCVRn(1)) \
CASE_##op((val), TRCDVCVRn(2)) \
CASE_##op((val), TRCDVCVRn(3)) \
CASE_##op((val), TRCDVCVRn(4)) \
CASE_##op((val), TRCDVCVRn(5)) \
CASE_##op((val), TRCDVCVRn(6)) \
CASE_##op((val), TRCDVCVRn(7)) \
CASE_##op((val), TRCDVCMRn(0)) \
CASE_##op((val), TRCDVCMRn(1)) \
CASE_##op((val), TRCDVCMRn(2)) \
CASE_##op((val), TRCDVCMRn(3)) \
CASE_##op((val), TRCDVCMRn(4)) \
CASE_##op((val), TRCDVCMRn(5)) \
CASE_##op((val), TRCDVCMRn(6)) \
CASE_##op((val), TRCDVCMRn(7)) \
CASE_##op((val), TRCCIDCVRn(0)) \
CASE_##op((val), TRCCIDCVRn(1)) \
CASE_##op((val), TRCCIDCVRn(2)) \
CASE_##op((val), TRCCIDCVRn(3)) \
CASE_##op((val), TRCCIDCVRn(4)) \
CASE_##op((val), TRCCIDCVRn(5)) \
CASE_##op((val), TRCCIDCVRn(6)) \
CASE_##op((val), TRCCIDCVRn(7)) \
CASE_##op((val), TRCVMIDCVRn(0)) \
CASE_##op((val), TRCVMIDCVRn(1)) \
CASE_##op((val), TRCVMIDCVRn(2)) \
CASE_##op((val), TRCVMIDCVRn(3)) \
CASE_##op((val), TRCVMIDCVRn(4)) \
CASE_##op((val), TRCVMIDCVRn(5)) \
CASE_##op((val), TRCVMIDCVRn(6)) \
CASE_##op((val), TRCVMIDCVRn(7)) \
CASE_##op((val), TRCCIDCCTLR0) \
CASE_##op((val), TRCCIDCCTLR1) \
CASE_##op((val), TRCVMIDCCTLR0) \
CASE_##op((val), TRCVMIDCCTLR1) \
CASE_##op((val), TRCITCTRL) \
CASE_##op((val), TRCCLAIMSET) \
CASE_##op((val), TRCCLAIMCLR) \
CASE_##op((val), TRCDEVAFF0) \
CASE_##op((val), TRCDEVAFF1) \
CASE_##op((val), TRCLAR) \
CASE_##op((val), TRCLSR) \
CASE_##op((val), TRCAUTHSTATUS) \
CASE_##op((val), TRCDEVARCH) \
CASE_##op((val), TRCDEVID) \
CASE_##op((val), TRCDEVTYPE) \
CASE_##op((val), TRCPIDR4) \
CASE_##op((val), TRCPIDR5) \
CASE_##op((val), TRCPIDR6) \
CASE_##op((val), TRCPIDR7) \
CASE_##op((val), TRCPIDR0) \
CASE_##op((val), TRCPIDR1) \
CASE_##op((val), TRCPIDR2) \
CASE_##op((val), TRCPIDR3)
+#define ETM4x_READ_CASES(res) CASE_LIST(READ, (res)) +#define ETM4x_WRITE_CASES(val) CASE_LIST(WRITE, (val))
+#define read_etm4x_sysreg_offset(csa, offset, _64bit) \
({ \
u64 __val; \
\
if (__builtin_constant_p((offset))) \
__val = read_etm4x_sysreg_const_offset((offset)); \
else \
__val = etm4x_sysreg_read((csa), (offset), \
true, _64bit); \
__val; \
})
+#define write_etm4x_sysreg_offset(csa, val, offset, _64bit) \
do { \
if (__builtin_constant_p((offset))) \
write_etm4x_sysreg_const_offset((val), \
(offset)); \
else \
etm4x_sysreg_write((csa), (val), (offset), \
true, _64bit); \
} while (0)
+#define etm4x_relaxed_read32(csa, offset) \
(u32)((csa)->io_mem ? \
readl_relaxed((csa)->base + (offset)) : \
read_etm4x_sysreg_offset((csa), (offset), false))
+#define etm4x_relaxed_read64(csa, offset) \
(u64)((csa)->io_mem ? \
readq_relaxed((csa)->base + (offset)) : \
read_etm4x_sysreg_offset((csa), (offset), true))
+#define etm4x_read32(csa, offset) \
({ \
u32 __val = etm4x_relaxed_read32((csa), (offset)); \
__iormb(__val); \
__val; \
})
+#define etm4x_read64(csa, offset) \
({ \
u64 __val = etm4x_relaxed_read64((csa), (offset)); \
__iormb(__val); \
__val; \
})
+#define etm4x_relaxed_write32(csa, val, offset) \
do { \
if ((csa)->io_mem) \
writel_relaxed((val), (csa)->base + (offset)); \
else \
write_etm4x_sysreg_offset((csa), (val), \
(offset), false); \
} while (0)
+#define etm4x_relaxed_write64(csa, val, offset) \
do { \
if ((csa)->io_mem) \
writeq_relaxed((val), (csa)->base + (offset)); \
else \
write_etm4x_sysreg_offset((csa), (val), \
(offset), true); \
} while (0)
+#define etm4x_write32(csa, val, offset) \
do { \
__iowmb(); \
etm4x_relaxed_write32((csa), (val), (offset)); \
} while (0)
+#define etm4x_write64(csa, val, offset) \
do { \
__iowmb(); \
etm4x_relaxed_write64((csa), (val), (offset)); \
} while (0)
-#define etm4x_write64(csa, val, offset) \
writeq((val), (csa)->base + (offset))
/* ETMv4 resources */ #define ETM_MAX_NR_PE 8 @@ -509,4 +803,14 @@ enum etm_addr_ctxtype {
extern const struct attribute_group *coresight_etmv4_groups[]; void etm4_config_trace_mode(struct etmv4_config *config);
+u64 etm4x_sysreg_read(struct csdev_access *csa,
u32 offset,
bool _relaxed,
bool _64bit);
+void etm4x_sysreg_write(struct csdev_access *csa,
u64 val,
u32 offset,
bool _relaxed,
bool _64bit);
#endif
2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Define the fields of the DEVARCH register for identifying a component as an ETMv4.x unit. Going forward, we use the DEVARCH register for the component identification, rather than the TRCIDR3.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.c | 4 ++-- drivers/hwtracing/coresight/coresight-etm4x.h | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 40f8113191e0..34b27c26591b 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1598,8 +1598,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) static struct amba_cs_uci_id uci_id_etm4[] = { { /* ETMv4 UCI data */ - .devarch = 0x47704a13, - .devarch_mask = 0xfff0ffff, + .devarch = ETM_DEVARCH_ETMv4x_ARCH, + .devarch_mask = ETM_DEVARCH_ID_MASK, .devtype = 0x00000013, } }; diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 4044676d2385..29ffad6a5279 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -497,6 +497,24 @@ ETM_MODE_EXCL_KERN | \ ETM_MODE_EXCL_USER)
+#define ETM_DEVARCH_ARCHITECT_MASK GENMASK(31, 21) +#define ETM_DEVARCH_ARCHITECT_ARM ((0x4 << 28) | (0b0111011 << 21)) +#define ETM_DEVARCH_PRESENT BIT(20) +#define ETM_DEVARCH_REVISION_MASK GENMASK(19, 16) +#define ETM_DEVARCH_REVISION_SHIFT 16 +#define ETM_DEVARCH_ARCHID_MASK GENMASK(15, 0) +#define ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT 12 +#define ETM_DEVARCH_ARCHID_ARCH_VER(x) \ + (((x) & 0xfUL) << ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT) +#define ETM_DEVARCH_ARCHID_ARCH_PART(x) ((x) & 0xfffUL) +#define ETM_DEVARCH_ARCHID_ETMv4 \ + (ETM_DEVARCH_ARCHID_ARCH_VER(4) | ETM_DEVARCH_ARCHID_ARCH_PART(0xA13)) + +#define ETM_DEVARCH_ID_MASK \ + (ETM_DEVARCH_ARCHITECT_MASK | ETM_DEVARCH_ARCHID_MASK | ETM_DEVARCH_PRESENT) +#define ETM_DEVARCH_ETMv4x_ARCH \ + (ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETMv4 | ETM_DEVARCH_PRESENT) + #define TRCSTATR_IDLE_BIT 0 #define TRCSTATR_PMSTABLE_BIT 1 #define ETM_DEFAULT_ADDR_COMP 0
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Define the fields of the DEVARCH register for identifying a component as an ETMv4.x unit. Going forward, we use the DEVARCH register for the component identification, rather than the TRCIDR3.
TRCIDR1? - but either way, we are not using this for component ID. For the AMBA path component ID is made using CID + PID + optionally if in the table UCI - which includes DEVARCH. TRCIDR1 is simply used to get the architecture version so we can be sure the driver supports it, and can adjust behaviour for version dependent elements.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 4 ++-- drivers/hwtracing/coresight/coresight-etm4x.h | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 40f8113191e0..34b27c26591b 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1598,8 +1598,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) static struct amba_cs_uci_id uci_id_etm4[] = { { /* ETMv4 UCI data */
.devarch = 0x47704a13,
.devarch_mask = 0xfff0ffff,
.devarch = ETM_DEVARCH_ETMv4x_ARCH,
.devarch_mask = ETM_DEVARCH_ID_MASK, .devtype = 0x00000013,
Perhaps a good time to change this to a #define constant too. I assume that if the system access is going to use the coresight architected registers for ID - it should use the same set as the AMBA path - i.e. DEVARCH + DEVTYPE.
}
}; diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 4044676d2385..29ffad6a5279 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -497,6 +497,24 @@ ETM_MODE_EXCL_KERN | \ ETM_MODE_EXCL_USER)
+#define ETM_DEVARCH_ARCHITECT_MASK GENMASK(31, 21) +#define ETM_DEVARCH_ARCHITECT_ARM ((0x4 << 28) | (0b0111011 << 21)) +#define ETM_DEVARCH_PRESENT BIT(20) +#define ETM_DEVARCH_REVISION_MASK GENMASK(19, 16) +#define ETM_DEVARCH_REVISION_SHIFT 16 +#define ETM_DEVARCH_ARCHID_MASK GENMASK(15, 0) +#define ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT 12 +#define ETM_DEVARCH_ARCHID_ARCH_VER(x) \
(((x) & 0xfUL) << ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT)
+#define ETM_DEVARCH_ARCHID_ARCH_PART(x) ((x) & 0xfffUL) +#define ETM_DEVARCH_ARCHID_ETMv4 \
(ETM_DEVARCH_ARCHID_ARCH_VER(4) | ETM_DEVARCH_ARCHID_ARCH_PART(0xA13))
+#define ETM_DEVARCH_ID_MASK \
(ETM_DEVARCH_ARCHITECT_MASK | ETM_DEVARCH_ARCHID_MASK | ETM_DEVARCH_PRESENT)
+#define ETM_DEVARCH_ETMv4x_ARCH \
(ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETMv4 | ETM_DEVARCH_PRESENT)
#define TRCSTATR_IDLE_BIT 0 #define TRCSTATR_PMSTABLE_BIT 1
#define ETM_DEFAULT_ADDR_COMP 0
2.24.1
Regards
Mike -- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Hi Mike
On 09/18/2020 04:34 PM, Mike Leach wrote:
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Define the fields of the DEVARCH register for identifying a component as an ETMv4.x unit. Going forward, we use the DEVARCH register for the component identification, rather than the TRCIDR3.
TRCIDR1? - but either way, we are not using this for component ID. For
Sorry, it is TRCIDR1. Got it mixed with the TRCIDR3 for exlevel mask.
the AMBA path component ID is made using CID + PID + optionally if in the table UCI - which includes DEVARCH. TRCIDR1 is simply used to get the architecture version so we can be sure the driver supports it, and can adjust behaviour for version dependent elements.
Correct. The idea is to use the TRCDEVARCH instead of the TRCIDR1 for drvdata->arch. We use drvdata->arch to detect if the ETM is supported. At the moment, we blindly support all ETMv4.x components. With the system instruction support, we want to make sure we use a CoreSight architected register and not an ETM architected one to detect if the component is an ETM.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 4 ++-- drivers/hwtracing/coresight/coresight-etm4x.h | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 40f8113191e0..34b27c26591b 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1598,8 +1598,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) static struct amba_cs_uci_id uci_id_etm4[] = { { /* ETMv4 UCI data */
.devarch = 0x47704a13,
.devarch_mask = 0xfff0ffff,
.devarch = ETM_DEVARCH_ETMv4x_ARCH,
.devarch_mask = ETM_DEVARCH_ID_MASK, .devtype = 0x00000013,
Perhaps a good time to change this to a #define constant too.
Yes, I can change it.
I assume that if the system access is going to use the coresight architected registers for ID - it should use the same set as the AMBA path - i.e. DEVARCH + DEVTYPE.
I doubt if DEVTYPE is necessary when we are doing a system instruction access from the CPU. The DEVTYPE identifies the component as PE and a trace source. Both of which are implicit with the system instruction access, but is mandatory for an AMBA bus discovery as it is memory mapped. Moreover the TRCDEVTYPE is only accessible from the memory mapped interface and the external debugger interface. (as per ETM TRM).
Thanks for the review.
Suzuki
An ETM instance may not implement the OS/Software Lock. This is advertised via TRCOSLSR/TRCLSR respectively. Detect the presence of these lock registers and skip the lock/unlock if they are not implemented.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.c | 77 +++++++++++++++---- drivers/hwtracing/coresight/coresight-etm4x.h | 24 +++++- 2 files changed, 83 insertions(+), 18 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 34b27c26591b..7feb57108bdc 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -95,12 +95,19 @@ void etm4x_sysreg_write(struct csdev_access *csa, } }
+static inline bool etm4_os_lock_implemented(struct etmv4_drvdata *drvdata) +{ + return drvdata->os_lock_model == ETM_OS_LOCK_IMPLEMENTED; +} + static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { - /* Writing 0 to TRCOSLAR unlocks the trace registers */ - etm4x_relaxed_write32(csa, 0x0, TRCOSLAR); + if (etm4_os_lock_implemented(drvdata)) { + /* Writing 0 to TRCOSLAR unlocks the trace registers */ + etm4x_relaxed_write32(csa, 0x0, TRCOSLAR); + isb(); + } drvdata->os_unlock = true; - isb(); }
static void etm4_os_unlock(struct etmv4_drvdata *drvdata) @@ -115,10 +122,26 @@ static void etm4_os_lock(struct etmv4_drvdata *drvdata) if (WARN_ON(!drvdata->csdev)) return;
- /* Writing 0x1 to TRCOSLAR locks the trace registers */ - etm4x_relaxed_write32(&drvdata->csdev->access, 0x1, TRCOSLAR); + if (etm4_os_lock_implemented(drvdata)) { + /* Writing 0x1 to TRCOSLAR locks the trace registers */ + etm4x_relaxed_write32(&drvdata->csdev->access, 0x1, TRCOSLAR); + isb(); + } drvdata->os_unlock = false; - isb(); +} + +static void etm4_cs_lock(struct etmv4_drvdata *drvdata, + struct csdev_access *csa) +{ + if (drvdata->sw_lock) + CS_LOCK(csa); +} + +static void etm4_cs_unlock(struct etmv4_drvdata *drvdata, + struct csdev_access *csa) +{ + if (drvdata->sw_lock) + CS_UNLOCK(csa); }
static bool etm4_arch_supported(u8 arch) @@ -160,7 +183,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) struct device *etm_dev = &csdev->dev; struct csdev_access *csa = &csdev->access;
- CS_UNLOCK(csa); + etm4_cs_unlock(drvdata, csa);
etm4_os_unlock(drvdata);
@@ -258,7 +281,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) isb();
done: - CS_LOCK(csa); + etm4_cs_lock(drvdata, csa);
dev_dbg(etm_dev, "cpu: %d enable smp call done: %d\n", drvdata->cpu, rc); @@ -515,7 +538,7 @@ static void etm4_disable_hw(void *info) struct csdev_access *csa = &csdev->access; int i;
- CS_UNLOCK(csa); + etm4_cs_unlock(drvdata, csa);
if (!drvdata->skip_power_up) { /* power can be removed from the trace unit now */ @@ -557,7 +580,7 @@ static void etm4_disable_hw(void *info)
coresight_disclaim_device_unlocked(csdev);
- CS_LOCK(csa); + etm4_cs_lock(drvdata, csa);
dev_dbg(&drvdata->csdev->dev, "cpu: %d disable smp call done\n", drvdata->cpu); @@ -652,6 +675,20 @@ static const struct coresight_ops etm4_cs_ops = { .source_ops = &etm4_source_ops, };
+/* + * ETM may or may not implement the Software Lock and the OS Lock. + * Detect this before we attempt to do any locking. + */ +static void etm_detect_lock_status(struct etmv4_drvdata *drvdata, + struct csdev_access *csa) +{ + u32 sw_lsr = etm4x_relaxed_read32(csa, TRCLSR); + u32 os_lsr = etm4x_relaxed_read32(csa, TRCOSLSR); + + drvdata->sw_lock = TRCLSR_SLI(sw_lsr); + drvdata->os_lock_model = TRCOSLSR_OSM(os_lsr); +} + static void etm4_init_arch_data(void *info) { u32 etmidr0; @@ -664,10 +701,15 @@ static void etm4_init_arch_data(void *info) int i; struct csdev_access csa = CSDEV_ACCESS_IOMEM(drvdata->base);
+ /* + * We must check if the locks are implemented + * as early as possible. + */ + etm_detect_lock_status(drvdata, &csa); + /* Make sure all registers are accessible */ etm4_os_unlock_csa(drvdata, &csa); - - CS_UNLOCK(&csa); + etm4_cs_unlock(drvdata, &csa);
/* find all capabilities of the tracing unit */ etmidr0 = etm4x_relaxed_read32(&csa, TRCIDR0); @@ -821,7 +863,8 @@ static void etm4_init_arch_data(void *info) drvdata->nrseqstate = BMVAL(etmidr5, 25, 27); /* NUMCNTR, bits[30:28] number of counters available for tracing */ drvdata->nr_cntr = BMVAL(etmidr5, 28, 30); - CS_LOCK(&csa); + + etm4_cs_lock(drvdata, &csa); }
/* Set ELx trace filter access in the TRCVICTLR register */ @@ -1202,7 +1245,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) dsb(sy); isb();
- CS_UNLOCK(csa); + etm4_cs_unlock(drvdata, csa);
/* Lock the OS lock to disable trace and external debugger access */ etm4_os_lock(drvdata); @@ -1309,7 +1352,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU), TRCPDCR);
out: - CS_LOCK(csa); + etm4_cs_lock(drvdata, csa); return ret; }
@@ -1324,7 +1367,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) return;
csa = &csdev->access; - CS_UNLOCK(csa); + etm4_cs_unlock(drvdata, csa);
etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
@@ -1404,7 +1447,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
/* Unlock the OS lock to re-enable trace and external debug access */ etm4_os_unlock(drvdata); - CS_LOCK(csa); + etm4_cs_lock(drvdata, csa); }
static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 29ffad6a5279..efd903688edd 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -417,7 +417,7 @@ if ((csa)->io_mem) \ writel_relaxed((val), (csa)->base + (offset)); \ else \ - write_etm4x_sysreg_offset((csa), (val), \ + write_etm4x_sysreg_offset((csa), (val), \ (offset), false); \ } while (0)
@@ -541,6 +541,22 @@ /* NS MON (EL3) mode never implemented */ #define ETM_EXLEVEL_NS_VICTLR_MASK GENMASK(22, 20)
+/* + * TRCOSLSR.OSM - Bit[3,0] + * + * 0b00 - Trace OS Lock is not implemented. + * 0b10 - Trace OS Lock is implemented. + */ +#define TRCOSLSR_OSM(x) ((((x) & BIT(3)) >> 2) | ((x) & BIT(0))) +#define ETM_OS_LOCK_IMPLEMENTED 0b10 + +/* + * TRCLSR.SLI - Bit[0] + * 0b0 - Software Lock is not implemented. + * 0b1 - Software Lock is implmented. + */ +#define TRCLSR_SLI(x) ((x) & BIT(0)) + /** * struct etmv4_config - configuration information related to an ETMv4 * @mode: Controls various modes supported by this ETM. @@ -726,6 +742,10 @@ struct etmv4_save_state { * supported for the corresponding Exception level. * @ns_ex_level:In non-secure state, indicates whether instruction tracing is * supported for the corresponding Exception level. + * @sw_lock: Cached value of TRCLSR.SLI, tells you whether the software lock + * is implemented. + * @os_lock_model: Cached value of TRCOSLSR.OSM, tells you whether OS lock + * is implemented. * @sticky_enable: true if ETM base configuration has been done. * @boot_enable:True if we should start tracing at boot time. * @os_unlock: True if access to management registers is allowed. @@ -782,6 +802,8 @@ struct etmv4_drvdata { u8 s_ex_level; u8 ns_ex_level; u8 q_support; + u8 sw_lock; + u8 os_lock_model; bool sticky_enable; bool boot_enable; bool os_unlock;
Hi Suzuki
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
An ETM instance may not implement the OS/Software Lock. This is advertised via TRCOSLSR/TRCLSR respectively. Detect the presence of these lock registers and skip the lock/unlock if they are not implemented.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 77 +++++++++++++++---- drivers/hwtracing/coresight/coresight-etm4x.h | 24 +++++- 2 files changed, 83 insertions(+), 18 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 34b27c26591b..7feb57108bdc 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -95,12 +95,19 @@ void etm4x_sysreg_write(struct csdev_access *csa, } }
+static inline bool etm4_os_lock_implemented(struct etmv4_drvdata *drvdata) +{
return drvdata->os_lock_model == ETM_OS_LOCK_IMPLEMENTED;
+}
static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata, struct csdev_access *csa) {
/* Writing 0 to TRCOSLAR unlocks the trace registers */
etm4x_relaxed_write32(csa, 0x0, TRCOSLAR);
if (etm4_os_lock_implemented(drvdata)) {
/* Writing 0 to TRCOSLAR unlocks the trace registers */
etm4x_relaxed_write32(csa, 0x0, TRCOSLAR);
isb();
} drvdata->os_unlock = true;
isb();
}
static void etm4_os_unlock(struct etmv4_drvdata *drvdata) @@ -115,10 +122,26 @@ static void etm4_os_lock(struct etmv4_drvdata *drvdata) if (WARN_ON(!drvdata->csdev)) return;
/* Writing 0x1 to TRCOSLAR locks the trace registers */
etm4x_relaxed_write32(&drvdata->csdev->access, 0x1, TRCOSLAR);
if (etm4_os_lock_implemented(drvdata)) {
/* Writing 0x1 to TRCOSLAR locks the trace registers */
etm4x_relaxed_write32(&drvdata->csdev->access, 0x1, TRCOSLAR);
isb();
} drvdata->os_unlock = false;
isb();
+}
+static void etm4_cs_lock(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
+{
if (drvdata->sw_lock)
CS_LOCK(csa);
+}
+static void etm4_cs_unlock(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
+{
if (drvdata->sw_lock)
CS_UNLOCK(csa);
}
static bool etm4_arch_supported(u8 arch) @@ -160,7 +183,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) struct device *etm_dev = &csdev->dev; struct csdev_access *csa = &csdev->access;
CS_UNLOCK(csa);
etm4_cs_unlock(drvdata, csa); etm4_os_unlock(drvdata);
@@ -258,7 +281,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) isb();
done:
CS_LOCK(csa);
etm4_cs_lock(drvdata, csa); dev_dbg(etm_dev, "cpu: %d enable smp call done: %d\n", drvdata->cpu, rc);
@@ -515,7 +538,7 @@ static void etm4_disable_hw(void *info) struct csdev_access *csa = &csdev->access; int i;
CS_UNLOCK(csa);
etm4_cs_unlock(drvdata, csa); if (!drvdata->skip_power_up) { /* power can be removed from the trace unit now */
@@ -557,7 +580,7 @@ static void etm4_disable_hw(void *info)
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(csa);
etm4_cs_lock(drvdata, csa); dev_dbg(&drvdata->csdev->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
@@ -652,6 +675,20 @@ static const struct coresight_ops etm4_cs_ops = { .source_ops = &etm4_source_ops, };
+/*
- ETM may or may not implement the Software Lock and the OS Lock.
- Detect this before we attempt to do any locking.
- */
+static void etm_detect_lock_status(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
+{
u32 sw_lsr = etm4x_relaxed_read32(csa, TRCLSR);
7.3.48 - ETMv4.5 spec -> TRCLSR accessible only from the memory mapped interface.
u32 os_lsr = etm4x_relaxed_read32(csa, TRCOSLSR);
This is unneeded. 7.3.50 of the ETM4.5 spec says for OS lock bits "always 0b10 for Armv8-A/R, Armv7-A/R,". So always implemented.
drvdata->sw_lock = TRCLSR_SLI(sw_lsr);
drvdata->os_lock_model = TRCOSLSR_OSM(os_lsr);
+}
static void etm4_init_arch_data(void *info) { u32 etmidr0; @@ -664,10 +701,15 @@ static void etm4_init_arch_data(void *info) int i; struct csdev_access csa = CSDEV_ACCESS_IOMEM(drvdata->base);
/*
* We must check if the locks are implemented
* as early as possible.
*/
etm_detect_lock_status(drvdata, &csa);
/* Make sure all registers are accessible */ etm4_os_unlock_csa(drvdata, &csa);
CS_UNLOCK(&csa);
etm4_cs_unlock(drvdata, &csa); /* find all capabilities of the tracing unit */ etmidr0 = etm4x_relaxed_read32(&csa, TRCIDR0);
@@ -821,7 +863,8 @@ static void etm4_init_arch_data(void *info) drvdata->nrseqstate = BMVAL(etmidr5, 25, 27); /* NUMCNTR, bits[30:28] number of counters available for tracing */ drvdata->nr_cntr = BMVAL(etmidr5, 28, 30);
CS_LOCK(&csa);
etm4_cs_lock(drvdata, &csa);
}
/* Set ELx trace filter access in the TRCVICTLR register */ @@ -1202,7 +1245,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) dsb(sy); isb();
CS_UNLOCK(csa);
etm4_cs_unlock(drvdata, csa); /* Lock the OS lock to disable trace and external debugger access */ etm4_os_lock(drvdata);
@@ -1309,7 +1352,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) etm4x_relaxed_write32(csa, (state->trcpdcr & ~TRCPDCR_PU), TRCPDCR);
out:
CS_LOCK(csa);
etm4_cs_lock(drvdata, csa); return ret;
}
@@ -1324,7 +1367,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata) return;
csa = &csdev->access;
CS_UNLOCK(csa);
etm4_cs_unlock(drvdata, csa); etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
@@ -1404,7 +1447,7 @@ static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
/* Unlock the OS lock to re-enable trace and external debug access */ etm4_os_unlock(drvdata);
CS_LOCK(csa);
etm4_cs_lock(drvdata, csa);
}
static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 29ffad6a5279..efd903688edd 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -417,7 +417,7 @@ if ((csa)->io_mem) \ writel_relaxed((val), (csa)->base + (offset)); \ else \
write_etm4x_sysreg_offset((csa), (val), \
write_etm4x_sysreg_offset((csa), (val), \ (offset), false); \ } while (0)
@@ -541,6 +541,22 @@ /* NS MON (EL3) mode never implemented */ #define ETM_EXLEVEL_NS_VICTLR_MASK GENMASK(22, 20)
+/*
- TRCOSLSR.OSM - Bit[3,0]
- 0b00 - Trace OS Lock is not implemented.
- 0b10 - Trace OS Lock is implemented.
- */
+#define TRCOSLSR_OSM(x) ((((x) & BIT(3)) >> 2) | ((x) & BIT(0))) +#define ETM_OS_LOCK_IMPLEMENTED 0b10
As per my comment above - can be dropped as always implemented.
+/*
- TRCLSR.SLI - Bit[0]
- 0b0 - Software Lock is not implemented.
- 0b1 - Software Lock is implmented.
- */
+#define TRCLSR_SLI(x) ((x) & BIT(0))
/**
- struct etmv4_config - configuration information related to an ETMv4
- @mode: Controls various modes supported by this ETM.
@@ -726,6 +742,10 @@ struct etmv4_save_state {
supported for the corresponding Exception level.
- @ns_ex_level:In non-secure state, indicates whether instruction tracing is
supported for the corresponding Exception level.
- @sw_lock: Cached value of TRCLSR.SLI, tells you whether the software lock
is implemented.
- @os_lock_model: Cached value of TRCOSLSR.OSM, tells you whether OS lock
is implemented.
- @sticky_enable: true if ETM base configuration has been done.
- @boot_enable:True if we should start tracing at boot time.
- @os_unlock: True if access to management registers is allowed.
@@ -782,6 +802,8 @@ struct etmv4_drvdata { u8 s_ex_level; u8 ns_ex_level; u8 q_support;
u8 sw_lock;
u8 os_lock_model; bool sticky_enable; bool boot_enable; bool os_unlock;
-- 2.24.1
Regards
Mike -- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
On 09/18/2020 04:35 PM, Mike Leach wrote:
Hi Suzuki
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
An ETM instance may not implement the OS/Software Lock. This is advertised via TRCOSLSR/TRCLSR respectively. Detect the presence of these lock registers and skip the lock/unlock if they are not implemented.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 77 +++++++++++++++---- drivers/hwtracing/coresight/coresight-etm4x.h | 24 +++++- 2 files changed, 83 insertions(+), 18 deletions(-)
+/*
- ETM may or may not implement the Software Lock and the OS Lock.
- Detect this before we attempt to do any locking.
- */
+static void etm_detect_lock_status(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
+{
u32 sw_lsr = etm4x_relaxed_read32(csa, TRCLSR);
7.3.48 - ETMv4.5 spec -> TRCLSR accessible only from the memory mapped interface.
Good point, I have fixed this now.
u32 os_lsr = etm4x_relaxed_read32(csa, TRCOSLSR);
This is unneeded. 7.3.50 of the ETM4.5 spec says for OS lock bits "always 0b10 for Armv8-A/R, Armv7-A/R,". So always implemented.
Agreed, I will drop this for now.
Cheers Suzuki
We rely on the ETM architecture version to decide whether Secure EL2 is available on the CPU for excluding the level for address comparators and viewinst main control register. We must instead use the TRCDIDR3.EXLEVEL_S field to detect the supported levels.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.c | 13 +++---------- drivers/hwtracing/coresight/coresight-etm4x.h | 6 ++++-- 2 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 7feb57108bdc..439e9da41006 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -758,7 +758,6 @@ static void etm4_init_arch_data(void *info) * TRCARCHMAJ, bits[11:8] architecture major versin number */ drvdata->arch = BMVAL(etmidr1, 4, 11); - drvdata->config.arch = drvdata->arch;
/* maximum size of resources */ etmidr2 = etm4x_relaxed_read32(&csa, TRCIDR2); @@ -774,6 +773,7 @@ static void etm4_init_arch_data(void *info) drvdata->ccitmin = BMVAL(etmidr3, 0, 11); /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ drvdata->s_ex_level = BMVAL(etmidr3, 16, 19); + drvdata->config.s_ex_level = drvdata->s_ex_level; /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */ drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23);
@@ -935,16 +935,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config) static u64 etm4_get_access_type(struct etmv4_config *config) { u64 access_type = etm4_get_ns_access_type(config); - u64 s_hyp = (config->arch & 0x0f) >= 0x4 ? ETM_EXLEVEL_S_HYP : 0;
- /* - * EXLEVEL_S, bits[11:8], don't trace anything happening - * in secure state. - */ - access_type |= (ETM_EXLEVEL_S_APP | - ETM_EXLEVEL_S_OS | - s_hyp | - ETM_EXLEVEL_S_MON); + /* All supported secure ELs are excluded */ + access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
return access_type; } diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index efd903688edd..407ad6647f36 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -522,6 +522,8 @@ /* PowerDown Control Register bits */ #define TRCPDCR_PU BIT(3)
+#define TRCACATR_EXLEVEL_SHIFT 8 + /* secure state access levels - TRCACATRn */ #define ETM_EXLEVEL_S_APP BIT(8) #define ETM_EXLEVEL_S_OS BIT(9) @@ -604,7 +606,7 @@ * @vmid_mask0: VM ID comparator mask for comparator 0-3. * @vmid_mask1: VM ID comparator mask for comparator 4-7. * @ext_inp: External input selection. - * @arch: ETM architecture version (for arch dependent config). + * @s_ex_level: Secure ELs where tracing is supported. */ struct etmv4_config { u32 mode; @@ -648,7 +650,7 @@ struct etmv4_config { u32 vmid_mask0; u32 vmid_mask1; u32 ext_inp; - u8 arch; + u8 s_ex_level; };
/**
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
We rely on the ETM architecture version to decide whether Secure EL2 is available on the CPU for excluding the level for address comparators and viewinst main control register. We must instead use the TRCDIDR3.EXLEVEL_S field to detect the supported levels.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 13 +++---------- drivers/hwtracing/coresight/coresight-etm4x.h | 6 ++++-- 2 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 7feb57108bdc..439e9da41006 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -758,7 +758,6 @@ static void etm4_init_arch_data(void *info) * TRCARCHMAJ, bits[11:8] architecture major versin number */ drvdata->arch = BMVAL(etmidr1, 4, 11);
drvdata->config.arch = drvdata->arch; /* maximum size of resources */ etmidr2 = etm4x_relaxed_read32(&csa, TRCIDR2);
@@ -774,6 +773,7 @@ static void etm4_init_arch_data(void *info) drvdata->ccitmin = BMVAL(etmidr3, 0, 11); /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ drvdata->s_ex_level = BMVAL(etmidr3, 16, 19);
drvdata->config.s_ex_level = drvdata->s_ex_level; /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */ drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23);
@@ -935,16 +935,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config) static u64 etm4_get_access_type(struct etmv4_config *config) { u64 access_type = etm4_get_ns_access_type(config);
u64 s_hyp = (config->arch & 0x0f) >= 0x4 ? ETM_EXLEVEL_S_HYP : 0;
/*
* EXLEVEL_S, bits[11:8], don't trace anything happening
* in secure state.
*/
access_type |= (ETM_EXLEVEL_S_APP |
ETM_EXLEVEL_S_OS |
s_hyp |
ETM_EXLEVEL_S_MON);
/* All supported secure ELs are excluded */
access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
What is the << TRCACATR_EXLEVEL_SHIFT doing here?
return access_type;
} diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index efd903688edd..407ad6647f36 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -522,6 +522,8 @@ /* PowerDown Control Register bits */ #define TRCPDCR_PU BIT(3)
+#define TRCACATR_EXLEVEL_SHIFT 8
/* secure state access levels - TRCACATRn */ #define ETM_EXLEVEL_S_APP BIT(8) #define ETM_EXLEVEL_S_OS BIT(9) @@ -604,7 +606,7 @@
- @vmid_mask0: VM ID comparator mask for comparator 0-3.
- @vmid_mask1: VM ID comparator mask for comparator 4-7.
- @ext_inp: External input selection.
- @arch: ETM architecture version (for arch dependent config).
*/
- @s_ex_level: Secure ELs where tracing is supported.
struct etmv4_config { u32 mode; @@ -648,7 +650,7 @@ struct etmv4_config { u32 vmid_mask0; u32 vmid_mask1; u32 ext_inp;
u8 arch;
u8 s_ex_level;
};
/**
2.24.1
Perhaps this patch could be combined with the next patch as it operates on the same set of flags.
Regards
Mike -- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
On 09/18/2020 04:35 PM, Mike Leach wrote:
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
We rely on the ETM architecture version to decide whether Secure EL2 is available on the CPU for excluding the level for address comparators and viewinst main control register. We must instead use the TRCDIDR3.EXLEVEL_S field to detect the supported levels.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 13 +++---------- drivers/hwtracing/coresight/coresight-etm4x.h | 6 ++++-- 2 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 7feb57108bdc..439e9da41006 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -758,7 +758,6 @@ static void etm4_init_arch_data(void *info) * TRCARCHMAJ, bits[11:8] architecture major versin number */ drvdata->arch = BMVAL(etmidr1, 4, 11);
drvdata->config.arch = drvdata->arch; /* maximum size of resources */ etmidr2 = etm4x_relaxed_read32(&csa, TRCIDR2);
@@ -774,6 +773,7 @@ static void etm4_init_arch_data(void *info) drvdata->ccitmin = BMVAL(etmidr3, 0, 11); /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ drvdata->s_ex_level = BMVAL(etmidr3, 16, 19);
drvdata->config.s_ex_level = drvdata->s_ex_level; /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */ drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23);
@@ -935,16 +935,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config) static u64 etm4_get_access_type(struct etmv4_config *config) { u64 access_type = etm4_get_ns_access_type(config);
u64 s_hyp = (config->arch & 0x0f) >= 0x4 ? ETM_EXLEVEL_S_HYP : 0;
/*
* EXLEVEL_S, bits[11:8], don't trace anything happening
* in secure state.
*/
access_type |= (ETM_EXLEVEL_S_APP |
ETM_EXLEVEL_S_OS |
s_hyp |
ETM_EXLEVEL_S_MON);
/* All supported secure ELs are excluded */
access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
What is the << TRCACATR_EXLEVEL_SHIFT doing here?
The config->s_ex_level is the EXLVEL mask from the TRCIDR3 shifted to bit 0, as above. We need to make sure that we use the mask in the correct position for TRCACATR register. Basically, we simply exclude all the secure levels supported by the ETM.
return access_type;
} diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index efd903688edd..407ad6647f36 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -522,6 +522,8 @@ /* PowerDown Control Register bits */ #define TRCPDCR_PU BIT(3)
+#define TRCACATR_EXLEVEL_SHIFT 8
- /* secure state access levels - TRCACATRn */ #define ETM_EXLEVEL_S_APP BIT(8) #define ETM_EXLEVEL_S_OS BIT(9)
@@ -604,7 +606,7 @@
- @vmid_mask0: VM ID comparator mask for comparator 0-3.
- @vmid_mask1: VM ID comparator mask for comparator 4-7.
- @ext_inp: External input selection.
- @arch: ETM architecture version (for arch dependent config).
*/ struct etmv4_config { u32 mode;
- @s_ex_level: Secure ELs where tracing is supported.
@@ -648,7 +650,7 @@ struct etmv4_config { u32 vmid_mask0; u32 vmid_mask1; u32 ext_inp;
u8 arch;
u8 s_ex_level;
};
/**
-- 2.24.1
Perhaps this patch could be combined with the next patch as it operates on the same set of flags.
I agree that they both deal with the same set of masks. However, functionally they have separate purposes.
1) This patch disconnects the usage of drvdata->arch field to determine the secure exception level mask. This is more of a correctness, as a given v4.4 implementation may not have a Secure EL2.
2) The next patch cleans up the way we define and use all the exception level masks, both secure and non-secure.
I understand that the subjects are quite similar. I could try to fix the subject for this one to make (1) more explicit. This way it is more easier to review.
Suzuki
Hi Suzuki,
On Tue, 22 Sep 2020 at 11:51, Suzuki K Poulose suzuki.poulose@arm.com wrote:
On 09/18/2020 04:35 PM, Mike Leach wrote:
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
We rely on the ETM architecture version to decide whether Secure EL2 is available on the CPU for excluding the level for address comparators and viewinst main control register. We must instead use the TRCDIDR3.EXLEVEL_S field to detect the supported levels.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 13 +++---------- drivers/hwtracing/coresight/coresight-etm4x.h | 6 ++++-- 2 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 7feb57108bdc..439e9da41006 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -758,7 +758,6 @@ static void etm4_init_arch_data(void *info) * TRCARCHMAJ, bits[11:8] architecture major versin number */ drvdata->arch = BMVAL(etmidr1, 4, 11);
drvdata->config.arch = drvdata->arch; /* maximum size of resources */ etmidr2 = etm4x_relaxed_read32(&csa, TRCIDR2);
@@ -774,6 +773,7 @@ static void etm4_init_arch_data(void *info) drvdata->ccitmin = BMVAL(etmidr3, 0, 11); /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ drvdata->s_ex_level = BMVAL(etmidr3, 16, 19);
drvdata->config.s_ex_level = drvdata->s_ex_level; /* EXLEVEL_NS, bits[23:20] Non-secure state instruction tracing */ drvdata->ns_ex_level = BMVAL(etmidr3, 20, 23);
@@ -935,16 +935,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config) static u64 etm4_get_access_type(struct etmv4_config *config) { u64 access_type = etm4_get_ns_access_type(config);
u64 s_hyp = (config->arch & 0x0f) >= 0x4 ? ETM_EXLEVEL_S_HYP : 0;
/*
* EXLEVEL_S, bits[11:8], don't trace anything happening
* in secure state.
*/
access_type |= (ETM_EXLEVEL_S_APP |
ETM_EXLEVEL_S_OS |
s_hyp |
ETM_EXLEVEL_S_MON);
/* All supported secure ELs are excluded */
access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
What is the << TRCACATR_EXLEVEL_SHIFT doing here?
The config->s_ex_level is the EXLVEL mask from the TRCIDR3 shifted to bit 0, as above. We need to make sure that we use the mask in the correct position for TRCACATR register. Basically, we simply exclude all the secure levels supported by the ETM.
Sorry, should have been a little more explicit. This breaks the next patch!
return access_type;
} diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index efd903688edd..407ad6647f36 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -522,6 +522,8 @@ /* PowerDown Control Register bits */ #define TRCPDCR_PU BIT(3)
+#define TRCACATR_EXLEVEL_SHIFT 8
- /* secure state access levels - TRCACATRn */ #define ETM_EXLEVEL_S_APP BIT(8) #define ETM_EXLEVEL_S_OS BIT(9)
@@ -604,7 +606,7 @@
- @vmid_mask0: VM ID comparator mask for comparator 0-3.
- @vmid_mask1: VM ID comparator mask for comparator 4-7.
- @ext_inp: External input selection.
- @arch: ETM architecture version (for arch dependent config).
*/ struct etmv4_config { u32 mode;
- @s_ex_level: Secure ELs where tracing is supported.
@@ -648,7 +650,7 @@ struct etmv4_config { u32 vmid_mask0; u32 vmid_mask1; u32 ext_inp;
u8 arch;
u8 s_ex_level;
};
/**
-- 2.24.1
Perhaps this patch could be combined with the next patch as it operates on the same set of flags.
I agree that they both deal with the same set of masks. However, functionally they have separate purposes.
- This patch disconnects the usage of drvdata->arch field to determine
the secure exception level mask. This is more of a correctness, as a given v4.4 implementation may not have a Secure EL2.
- The next patch cleans up the way we define and use all the exception level
masks, both secure and non-secure.
Applying this and the next patch which moves to the bits being indexed from 0 for a common reusable field gets you the following code sequence:-
static u64 etm4_get_ns_access_type(struct etmv4_config *config) { u64 access_type = 0;
/* * EXLEVEL_NS, bits[15:12] * The Exception levels are: * Bit[12] Exception level 0 - Application * Bit[13] Exception level 1 - OS * Bit[14] Exception level 2 - Hypervisor * Bit[15] Never implemented */
[ MJL: at this point the comment is true to an extent but no longer applies to the values #defines below - which have been shifted by the change to the #defines to form a field that is indexed from bit 0]
if (!is_kernel_in_hyp_mode()) { /* Stay away from hypervisor mode for non-VHE */ access_type = ETM_EXLEVEL_NS_HYP; if (config->mode & ETM_MODE_EXCL_KERN) access_type |= ETM_EXLEVEL_NS_OS; } else if (config->mode & ETM_MODE_EXCL_KERN) { access_type = ETM_EXLEVEL_NS_HYP; }
if (config->mode & ETM_MODE_EXCL_USER) access_type |= ETM_EXLEVEL_NS_APP;
return access_type; }
static u64 etm4_get_access_type(struct etmv4_config *config) { u64 access_type = etm4_get_ns_access_type(config);
/* All supported secure ELs are excluded */ access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
[MJL: Now we are OR ing a 0 bit index based field (NS access type) with another 0 index based field - but shifting it for some reason?]
return access_type; }
static u64 etm4_get_comparator_access_type(struct etmv4_config *config) { return etm4_get_access_type(config) << TRCACATR_EXLEVEL_SHIFT;
[MJL: resulting in TRCACATR_EXLEVEL_SHIFT being applied twice.] }
Hence my assertion that this should really be one patch, otherwise you have to add the shift in one patch and correct the problem in the second.
Regards
Mike
I understand that the subjects are quite similar. I could try to fix the subject for this one to make (1) more explicit. This way it is more easier to review.
Suzuki
Hi Mike,
On 09/22/2020 01:47 PM, Mike Leach wrote:
Hi Suzuki,
@@ -935,16 +935,9 @@ static u64 etm4_get_ns_access_type(struct etmv4_config *config) static u64 etm4_get_access_type(struct etmv4_config *config) { u64 access_type = etm4_get_ns_access_type(config);
u64 s_hyp = (config->arch & 0x0f) >= 0x4 ? ETM_EXLEVEL_S_HYP : 0;
/*
* EXLEVEL_S, bits[11:8], don't trace anything happening
* in secure state.
*/
access_type |= (ETM_EXLEVEL_S_APP |
ETM_EXLEVEL_S_OS |
s_hyp |
ETM_EXLEVEL_S_MON);
/* All supported secure ELs are excluded */
access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
What is the << TRCACATR_EXLEVEL_SHIFT doing here?
The config->s_ex_level is the EXLVEL mask from the TRCIDR3 shifted to bit 0, as above. We need to make sure that we use the mask in the correct position for TRCACATR register. Basically, we simply exclude all the secure levels supported by the ETM.
Sorry, should have been a little more explicit. This breaks the next patch!
return access_type;
} diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index efd903688edd..407ad6647f36 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -522,6 +522,8 @@ /* PowerDown Control Register bits */ #define TRCPDCR_PU BIT(3)
+#define TRCACATR_EXLEVEL_SHIFT 8
- /* secure state access levels - TRCACATRn */ #define ETM_EXLEVEL_S_APP BIT(8) #define ETM_EXLEVEL_S_OS BIT(9)
@@ -604,7 +606,7 @@ * @vmid_mask0: VM ID comparator mask for comparator 0-3. * @vmid_mask1: VM ID comparator mask for comparator 4-7. * @ext_inp: External input selection.
- @arch: ETM architecture version (for arch dependent config).
struct etmv4_config { u32 mode;
- @s_ex_level: Secure ELs where tracing is supported. */
@@ -648,7 +650,7 @@ struct etmv4_config { u32 vmid_mask0; u32 vmid_mask1; u32 ext_inp;
u8 arch;
u8 s_ex_level;
};
/**
-- 2.24.1
Perhaps this patch could be combined with the next patch as it operates on the same set of flags.
I agree that they both deal with the same set of masks. However, functionally they have separate purposes.
- This patch disconnects the usage of drvdata->arch field to determine
the secure exception level mask. This is more of a correctness, as a given v4.4 implementation may not have a Secure EL2.
- The next patch cleans up the way we define and use all the exception level
masks, both secure and non-secure.
Applying this and the next patch which moves to the bits being indexed from 0 for a common reusable field gets you the following code sequence:-
Good catch.
static u64 etm4_get_ns_access_type(struct etmv4_config *config) { u64 access_type = 0;
/* * EXLEVEL_NS, bits[15:12] * The Exception levels are: * Bit[12] Exception level 0 - Application * Bit[13] Exception level 1 - OS * Bit[14] Exception level 2 - Hypervisor * Bit[15] Never implemented */
Updated the comments.
[ MJL: at this point the comment is true to an extent but no longer applies to the values #defines below - which have been shifted by the change to the #defines to form a field that is indexed from bit 0]
static u64 etm4_get_access_type(struct etmv4_config *config) { u64 access_type = etm4_get_ns_access_type(config);
/* All supported secure ELs are excluded */ access_type |= (u64)config->s_ex_level << TRCACATR_EXLEVEL_SHIFT;
[MJL: Now we are OR ing a 0 bit index based field (NS access type) with another 0 index based field - but shifting it for some reason?]
That was a mistake. I will drop this shift from here to make get_access_type() and this should work.
Suzuki
etm4_get_access_type() calculates the exception level bits for use in address comparator registers. This is also used by the TRCVICTLR register by shifting to the required position.
This patch cleans up the logic to make etm4_get_access_type() calcualte a generic mask which can be used by all users by shifting to their field.
No functional changes, only code cleanups.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- .../coresight/coresight-etm4x-sysfs.c | 12 +++--- drivers/hwtracing/coresight/coresight-etm4x.c | 27 ++++++------ drivers/hwtracing/coresight/coresight-etm4x.h | 43 ++++++++++++------- 3 files changed, 47 insertions(+), 35 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index 321ad0dc09b0..b18805694350 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -743,7 +743,7 @@ static ssize_t s_exlevel_vinst_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config;
- val = (config->vinst_ctrl & ETM_EXLEVEL_S_VICTLR_MASK) >> 16; + val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_S_MASK) >> TRCVICTLR_EXLEVEL_S_SHIFT; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); }
@@ -760,10 +760,10 @@ static ssize_t s_exlevel_vinst_store(struct device *dev,
spin_lock(&drvdata->spinlock); /* clear all EXLEVEL_S bits */ - config->vinst_ctrl &= ~(ETM_EXLEVEL_S_VICTLR_MASK); + config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_S_MASK); /* enable instruction tracing for corresponding exception level */ val &= drvdata->s_ex_level; - config->vinst_ctrl |= (val << 16); + config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_S_SHIFT); spin_unlock(&drvdata->spinlock); return size; } @@ -778,7 +778,7 @@ static ssize_t ns_exlevel_vinst_show(struct device *dev, struct etmv4_config *config = &drvdata->config;
/* EXLEVEL_NS, bits[23:20] */ - val = (config->vinst_ctrl & ETM_EXLEVEL_NS_VICTLR_MASK) >> 20; + val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_NS_MASK) >> TRCVICTLR_EXLEVEL_NS_SHIFT; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val); }
@@ -795,10 +795,10 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,
spin_lock(&drvdata->spinlock); /* clear EXLEVEL_NS bits */ - config->vinst_ctrl &= ~(ETM_EXLEVEL_NS_VICTLR_MASK); + config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_NS_MASK); /* enable instruction tracing for corresponding exception level */ val &= drvdata->ns_ex_level; - config->vinst_ctrl |= (val << 20); + config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_NS_SHIFT); spin_unlock(&drvdata->spinlock); return size; } diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 439e9da41006..53687ec06db9 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -867,20 +867,16 @@ static void etm4_init_arch_data(void *info) etm4_cs_lock(drvdata, &csa); }
+static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config) +{ + return etm4_get_access_type(config) << TRCVICTLR_EXLEVEL_SHIFT; +} + /* Set ELx trace filter access in the TRCVICTLR register */ static void etm4_set_victlr_access(struct etmv4_config *config) { - u64 access_type; - - config->vinst_ctrl &= ~(ETM_EXLEVEL_S_VICTLR_MASK | ETM_EXLEVEL_NS_VICTLR_MASK); - - /* - * TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering - * bits in vinst_ctrl, same bit pattern as TRCACATRn values returned by - * etm4_get_access_type() but with a relative shift in this register. - */ - access_type = etm4_get_access_type(config) << ETM_EXLEVEL_LSHIFT_TRCVICTLR; - config->vinst_ctrl |= (u32)access_type; + config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_S_MASK | TRCVICTLR_EXLEVEL_NS_MASK); + config->vinst_ctrl |= etm4_get_victlr_access_type(config); }
static void etm4_set_default_config(struct etmv4_config *config) @@ -942,10 +938,15 @@ static u64 etm4_get_access_type(struct etmv4_config *config) return access_type; }
+static u64 etm4_get_comparator_access_type(struct etmv4_config *config) +{ + return etm4_get_access_type(config) << TRCACATR_EXLEVEL_SHIFT; +} + static void etm4_set_comparator_filter(struct etmv4_config *config, u64 start, u64 stop, int comparator) { - u64 access_type = etm4_get_access_type(config); + u64 access_type = etm4_get_comparator_access_type(config);
/* First half of default address comparator */ config->addr_val[comparator] = start; @@ -980,7 +981,7 @@ static void etm4_set_start_stop_filter(struct etmv4_config *config, enum etm_addr_type type) { int shift; - u64 access_type = etm4_get_access_type(config); + u64 access_type = etm4_get_comparator_access_type(config);
/* Configure the comparator */ config->addr_val[comparator] = address; diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 407ad6647f36..277c22540db6 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -524,24 +524,35 @@
#define TRCACATR_EXLEVEL_SHIFT 8
-/* secure state access levels - TRCACATRn */ -#define ETM_EXLEVEL_S_APP BIT(8) -#define ETM_EXLEVEL_S_OS BIT(9) -#define ETM_EXLEVEL_S_HYP BIT(10) -#define ETM_EXLEVEL_S_MON BIT(11) -/* non-secure state access levels - TRCACATRn */ -#define ETM_EXLEVEL_NS_APP BIT(12) -#define ETM_EXLEVEL_NS_OS BIT(13) -#define ETM_EXLEVEL_NS_HYP BIT(14) -#define ETM_EXLEVEL_NS_NA BIT(15) - -/* access level control in TRCVICTLR - same bits as TRCACATRn but shifted */ -#define ETM_EXLEVEL_LSHIFT_TRCVICTLR 8 +/* + * Exception level mask for Secure and Non-Secure ELs. + * ETM defines the bits for EL control (e.g, TRVICTLR, TRCACTRn). + * The Secure and Non-Secure ELs are always to gether. + * Non-secure EL3 is never implemented. + */ +#define ETM_EXLEVEL_S_APP BIT(0) +#define ETM_EXLEVEL_S_OS BIT(1) +#define ETM_EXLEVEL_S_HYP BIT(2) +#define ETM_EXLEVEL_S_MON BIT(3) +#define ETM_EXLEVEL_NS_APP BIT(4) +#define ETM_EXLEVEL_NS_OS BIT(5) +#define ETM_EXLEVEL_NS_HYP BIT(6) + +#define ETM_EXLEVEL_MASK (GENMASK(6, 0)) +#define ETM_EXLEVEL_S_MASK (GENMASK(3, 0)) +#define ETM_EXLEVEL_NS_MASK (GENMASK(6, 4)) + +/* access level controls in TRCACATRn */ +#define TRCACATR_EXLEVEL_SHIFT 8 + +/* access level control in TRCVICTLR */ +#define TRCVICTLR_EXLEVEL_SHIFT 16 +#define TRCVICTLR_EXLEVEL_S_SHIFT 16 +#define TRCVICTLR_EXLEVEL_NS_SHIFT 20
/* secure / non secure masks - TRCVICTLR, IDR3 */ -#define ETM_EXLEVEL_S_VICTLR_MASK GENMASK(19, 16) -/* NS MON (EL3) mode never implemented */ -#define ETM_EXLEVEL_NS_VICTLR_MASK GENMASK(22, 20) +#define TRCVICTLR_EXLEVEL_S_MASK (ETM_EXLEVEL_S_MASK << TRCVICTLR_EXLEVEL_S_SHIFT) +#define TRCVICTLR_EXLEVEL_NS_MASK (ETM_EXLEVEL_NS_MASK << TRCVICTLR_EXLEVEL_NS_SHIFT)
/* * TRCOSLSR.OSM - Bit[3,0]
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
etm4_get_access_type() calculates the exception level bits for use in address comparator registers. This is also used by the TRCVICTLR register by shifting to the required position.
This patch cleans up the logic to make etm4_get_access_type() calcualte a generic mask which can be used by all users by
Spelling^^
shifting to their field.
No functional changes, only code cleanups.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
.../coresight/coresight-etm4x-sysfs.c | 12 +++--- drivers/hwtracing/coresight/coresight-etm4x.c | 27 ++++++------ drivers/hwtracing/coresight/coresight-etm4x.h | 43 ++++++++++++------- 3 files changed, 47 insertions(+), 35 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c index 321ad0dc09b0..b18805694350 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c +++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c @@ -743,7 +743,7 @@ static ssize_t s_exlevel_vinst_show(struct device *dev, struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent); struct etmv4_config *config = &drvdata->config;
val = (config->vinst_ctrl & ETM_EXLEVEL_S_VICTLR_MASK) >> 16;
val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_S_MASK) >> TRCVICTLR_EXLEVEL_S_SHIFT; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -760,10 +760,10 @@ static ssize_t s_exlevel_vinst_store(struct device *dev,
spin_lock(&drvdata->spinlock); /* clear all EXLEVEL_S bits */
config->vinst_ctrl &= ~(ETM_EXLEVEL_S_VICTLR_MASK);
config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_S_MASK); /* enable instruction tracing for corresponding exception level */ val &= drvdata->s_ex_level;
config->vinst_ctrl |= (val << 16);
config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_S_SHIFT); spin_unlock(&drvdata->spinlock); return size;
} @@ -778,7 +778,7 @@ static ssize_t ns_exlevel_vinst_show(struct device *dev, struct etmv4_config *config = &drvdata->config;
/* EXLEVEL_NS, bits[23:20] */
val = (config->vinst_ctrl & ETM_EXLEVEL_NS_VICTLR_MASK) >> 20;
val = (config->vinst_ctrl & TRCVICTLR_EXLEVEL_NS_MASK) >> TRCVICTLR_EXLEVEL_NS_SHIFT; return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -795,10 +795,10 @@ static ssize_t ns_exlevel_vinst_store(struct device *dev,
spin_lock(&drvdata->spinlock); /* clear EXLEVEL_NS bits */
config->vinst_ctrl &= ~(ETM_EXLEVEL_NS_VICTLR_MASK);
config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_NS_MASK); /* enable instruction tracing for corresponding exception level */ val &= drvdata->ns_ex_level;
config->vinst_ctrl |= (val << 20);
config->vinst_ctrl |= (val << TRCVICTLR_EXLEVEL_NS_SHIFT); spin_unlock(&drvdata->spinlock); return size;
} diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 439e9da41006..53687ec06db9 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -867,20 +867,16 @@ static void etm4_init_arch_data(void *info) etm4_cs_lock(drvdata, &csa); }
+static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config) +{
return etm4_get_access_type(config) << TRCVICTLR_EXLEVEL_SHIFT;
+}
/* Set ELx trace filter access in the TRCVICTLR register */ static void etm4_set_victlr_access(struct etmv4_config *config) {
u64 access_type;
config->vinst_ctrl &= ~(ETM_EXLEVEL_S_VICTLR_MASK | ETM_EXLEVEL_NS_VICTLR_MASK);
/*
* TRCVICTLR::EXLEVEL_NS:EXLEVELS: Set kernel / user filtering
* bits in vinst_ctrl, same bit pattern as TRCACATRn values returned by
* etm4_get_access_type() but with a relative shift in this register.
*/
access_type = etm4_get_access_type(config) << ETM_EXLEVEL_LSHIFT_TRCVICTLR;
config->vinst_ctrl |= (u32)access_type;
config->vinst_ctrl &= ~(TRCVICTLR_EXLEVEL_S_MASK | TRCVICTLR_EXLEVEL_NS_MASK);
config->vinst_ctrl |= etm4_get_victlr_access_type(config);
}
static void etm4_set_default_config(struct etmv4_config *config) @@ -942,10 +938,15 @@ static u64 etm4_get_access_type(struct etmv4_config *config) return access_type; }
+static u64 etm4_get_comparator_access_type(struct etmv4_config *config) +{
return etm4_get_access_type(config) << TRCACATR_EXLEVEL_SHIFT;
+}
static void etm4_set_comparator_filter(struct etmv4_config *config, u64 start, u64 stop, int comparator) {
u64 access_type = etm4_get_access_type(config);
u64 access_type = etm4_get_comparator_access_type(config); /* First half of default address comparator */ config->addr_val[comparator] = start;
@@ -980,7 +981,7 @@ static void etm4_set_start_stop_filter(struct etmv4_config *config, enum etm_addr_type type) { int shift;
u64 access_type = etm4_get_access_type(config);
u64 access_type = etm4_get_comparator_access_type(config); /* Configure the comparator */ config->addr_val[comparator] = address;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 407ad6647f36..277c22540db6 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -524,24 +524,35 @@
#define TRCACATR_EXLEVEL_SHIFT 8
#defined twice^^ - this one needs deleting.
-/* secure state access levels - TRCACATRn */ -#define ETM_EXLEVEL_S_APP BIT(8) -#define ETM_EXLEVEL_S_OS BIT(9) -#define ETM_EXLEVEL_S_HYP BIT(10) -#define ETM_EXLEVEL_S_MON BIT(11) -/* non-secure state access levels - TRCACATRn */ -#define ETM_EXLEVEL_NS_APP BIT(12) -#define ETM_EXLEVEL_NS_OS BIT(13) -#define ETM_EXLEVEL_NS_HYP BIT(14) -#define ETM_EXLEVEL_NS_NA BIT(15)
-/* access level control in TRCVICTLR - same bits as TRCACATRn but shifted */ -#define ETM_EXLEVEL_LSHIFT_TRCVICTLR 8 +/*
- Exception level mask for Secure and Non-Secure ELs.
- ETM defines the bits for EL control (e.g, TRVICTLR, TRCACTRn).
- The Secure and Non-Secure ELs are always to gether.
- Non-secure EL3 is never implemented.
- */
+#define ETM_EXLEVEL_S_APP BIT(0) +#define ETM_EXLEVEL_S_OS BIT(1) +#define ETM_EXLEVEL_S_HYP BIT(2) +#define ETM_EXLEVEL_S_MON BIT(3) +#define ETM_EXLEVEL_NS_APP BIT(4) +#define ETM_EXLEVEL_NS_OS BIT(5) +#define ETM_EXLEVEL_NS_HYP BIT(6)
+#define ETM_EXLEVEL_MASK (GENMASK(6, 0)) +#define ETM_EXLEVEL_S_MASK (GENMASK(3, 0)) +#define ETM_EXLEVEL_NS_MASK (GENMASK(6, 4))
+/* access level controls in TRCACATRn */ +#define TRCACATR_EXLEVEL_SHIFT 8
+/* access level control in TRCVICTLR */ +#define TRCVICTLR_EXLEVEL_SHIFT 16 +#define TRCVICTLR_EXLEVEL_S_SHIFT 16 +#define TRCVICTLR_EXLEVEL_NS_SHIFT 20
/* secure / non secure masks - TRCVICTLR, IDR3 */ -#define ETM_EXLEVEL_S_VICTLR_MASK GENMASK(19, 16) -/* NS MON (EL3) mode never implemented */ -#define ETM_EXLEVEL_NS_VICTLR_MASK GENMASK(22, 20) +#define TRCVICTLR_EXLEVEL_S_MASK (ETM_EXLEVEL_S_MASK << TRCVICTLR_EXLEVEL_S_SHIFT) +#define TRCVICTLR_EXLEVEL_NS_MASK (ETM_EXLEVEL_NS_MASK << TRCVICTLR_EXLEVEL_NS_SHIFT)
/*
- TRCOSLSR.OSM - Bit[3,0]
-- 2.24.1
Regards
Mike -- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
On 09/18/2020 04:35 PM, Mike Leach wrote:
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
etm4_get_access_type() calculates the exception level bits for use in address comparator registers. This is also used by the TRCVICTLR register by shifting to the required position.
This patch cleans up the logic to make etm4_get_access_type() calcualte a generic mask which can be used by all users by
Spelling^^
shifting to their field.
No functional changes, only code cleanups.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
Mike,
I will address all the comments. Thanks for the review !
Suzuki
In preparation to detect the support for system instruction support, move the detection of the device access to the target CPU.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.c | 65 ++++++++++++++----- 1 file changed, 50 insertions(+), 15 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 53687ec06db9..5880f105268f 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -56,6 +56,11 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
static enum cpuhp_state hp_online;
+struct etm_init_arg { + struct etmv4_drvdata *drvdata; + struct csdev_access *csa; +}; + u64 etm4x_sysreg_read(struct csdev_access *csa, u32 offset, bool _relaxed, @@ -689,6 +694,22 @@ static void etm_detect_lock_status(struct etmv4_drvdata *drvdata, drvdata->os_lock_model = TRCOSLSR_OSM(os_lsr); }
+static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, + struct csdev_access *csa) +{ + *csa = CSDEV_ACCESS_IOMEM(drvdata->base); + return true; +} + +static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata, + struct csdev_access *csa) +{ + if (drvdata->base) + return etm_init_iomem_access(drvdata, csa); + + return false; +} + static void etm4_init_arch_data(void *info) { u32 etmidr0; @@ -697,22 +718,34 @@ static void etm4_init_arch_data(void *info) u32 etmidr3; u32 etmidr4; u32 etmidr5; - struct etmv4_drvdata *drvdata = info; + struct etm_init_arg *init_arg = info; + struct etmv4_drvdata *drvdata; + struct csdev_access *csa; int i; - struct csdev_access csa = CSDEV_ACCESS_IOMEM(drvdata->base); + + drvdata = init_arg->drvdata; + csa = init_arg->csa; + + /* + * If we are unable to detect the access mechanism, + * or unable to detect the trace unit type, fail + * early. + */ + if (!etm_init_csdev_access(drvdata, csa)) + return;
/* * We must check if the locks are implemented * as early as possible. */ - etm_detect_lock_status(drvdata, &csa); + etm_detect_lock_status(drvdata, csa);
/* Make sure all registers are accessible */ - etm4_os_unlock_csa(drvdata, &csa); - etm4_cs_unlock(drvdata, &csa); + etm4_os_unlock_csa(drvdata, csa); + etm4_cs_unlock(drvdata, csa);
/* find all capabilities of the tracing unit */ - etmidr0 = etm4x_relaxed_read32(&csa, TRCIDR0); + etmidr0 = etm4x_relaxed_read32(csa, TRCIDR0);
/* INSTP0, bits[2:1] P0 tracing support field */ if (BMVAL(etmidr0, 1, 1) && BMVAL(etmidr0, 2, 2)) @@ -752,7 +785,7 @@ static void etm4_init_arch_data(void *info) drvdata->ts_size = BMVAL(etmidr0, 24, 28);
/* base architecture of trace unit */ - etmidr1 = etm4x_relaxed_read32(&csa, TRCIDR1); + etmidr1 = etm4x_relaxed_read32(csa, TRCIDR1); /* * TRCARCHMIN, bits[7:4] architecture the minor version number * TRCARCHMAJ, bits[11:8] architecture major versin number @@ -760,7 +793,7 @@ static void etm4_init_arch_data(void *info) drvdata->arch = BMVAL(etmidr1, 4, 11);
/* maximum size of resources */ - etmidr2 = etm4x_relaxed_read32(&csa, TRCIDR2); + etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2); /* CIDSIZE, bits[9:5] Indicates the Context ID size */ drvdata->ctxid_size = BMVAL(etmidr2, 5, 9); /* VMIDSIZE, bits[14:10] Indicates the VMID size */ @@ -768,7 +801,7 @@ static void etm4_init_arch_data(void *info) /* CCSIZE, bits[28:25] size of the cycle counter in bits minus 12 */ drvdata->ccsize = BMVAL(etmidr2, 25, 28);
- etmidr3 = etm4x_relaxed_read32(&csa, TRCIDR3); + etmidr3 = etm4x_relaxed_read32(csa, TRCIDR3); /* CCITMIN, bits[11:0] minimum threshold value that can be programmed */ drvdata->ccitmin = BMVAL(etmidr3, 0, 11); /* EXLEVEL_S, bits[19:16] Secure state instruction tracing */ @@ -814,7 +847,7 @@ static void etm4_init_arch_data(void *info) drvdata->nooverflow = false;
/* number of resources trace unit supports */ - etmidr4 = etm4x_relaxed_read32(&csa, TRCIDR4); + etmidr4 = etm4x_relaxed_read32(csa, TRCIDR4); /* NUMACPAIRS, bits[0:3] number of addr comparator pairs for tracing */ drvdata->nr_addr_cmp = BMVAL(etmidr4, 0, 3); /* NUMPC, bits[15:12] number of PE comparator inputs for tracing */ @@ -834,14 +867,14 @@ static void etm4_init_arch_data(void *info) drvdata->nr_ss_cmp = BMVAL(etmidr4, 20, 23); for (i = 0; i < drvdata->nr_ss_cmp; i++) { drvdata->config.ss_status[i] = - etm4x_relaxed_read32(&csa, TRCSSCSRn(i)); + etm4x_relaxed_read32(csa, 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 */ drvdata->numvmidc = BMVAL(etmidr4, 28, 31);
- etmidr5 = etm4x_relaxed_read32(&csa, TRCIDR5); + etmidr5 = etm4x_relaxed_read32(csa, TRCIDR5); /* NUMEXTIN, bits[8:0] number of external inputs implemented */ drvdata->nr_ext_inp = BMVAL(etmidr5, 0, 8); /* TRACEIDSIZE, bits[21:16] indicates the trace ID width */ @@ -864,7 +897,7 @@ static void etm4_init_arch_data(void *info) /* NUMCNTR, bits[30:28] number of counters available for tracing */ drvdata->nr_cntr = BMVAL(etmidr5, 28, 30);
- etm4_cs_lock(drvdata, &csa); + etm4_cs_lock(drvdata, csa); }
static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config) @@ -1538,6 +1571,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) struct etmv4_drvdata *drvdata; struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; + struct etm_init_arg init_arg = { 0 };
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) @@ -1565,7 +1599,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) return PTR_ERR(base);
drvdata->base = base; - desc.access = CSDEV_ACCESS_IOMEM(base);
spin_lock_init(&drvdata->spinlock);
@@ -1578,9 +1611,11 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) return -ENOMEM;
etmdrvdata[drvdata->cpu] = drvdata; + init_arg.drvdata = drvdata; + init_arg.csa = &desc.access;
if (smp_call_function_single(drvdata->cpu, - etm4_init_arch_data, drvdata, 1)) + etm4_init_arch_data, &init_arg, 1)) dev_err(dev, "ETM arch init failed\n");
if (etm4_arch_supported(drvdata->arch) == false) {
We have been using TRCIDR1 for detecting the ETM version. As we are about to discover the trace unit on a CPU, let us use a CoreSight architected register, instead of an ETM architected register for accurate detection on a CPU. e.g, a CPU might implement a custom trace unit, not an ETM.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.c | 50 ++++++++++--------- drivers/hwtracing/coresight/coresight-etm4x.h | 4 +- 2 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 5880f105268f..0fce9fb12cff 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -61,6 +61,17 @@ struct etm_init_arg { struct csdev_access *csa; };
+static inline u8 etm_devarch_arch(u32 devarch) +{ + return (devarch >> ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT) & 0xfUL; +} + +static inline u8 etm_devarch_rev(u32 devarch) +{ + return (devarch & ETM_DEVARCH_REVISION_MASK) >> + ETM_DEVARCH_REVISION_SHIFT; +} + u64 etm4x_sysreg_read(struct csdev_access *csa, u32 offset, bool _relaxed, @@ -149,18 +160,6 @@ static void etm4_cs_unlock(struct etmv4_drvdata *drvdata, CS_UNLOCK(csa); }
-static bool etm4_arch_supported(u8 arch) -{ - /* Mask out the minor version number */ - switch (arch & 0xf0) { - case ETM_ARCH_V4: - break; - default: - return false; - } - return true; -} - static int etm4_cpu_id(struct coresight_device *csdev) { struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -694,10 +693,23 @@ static void etm_detect_lock_status(struct etmv4_drvdata *drvdata, drvdata->os_lock_model = TRCOSLSR_OSM(os_lsr); }
+static inline bool trace_unit_supported(u32 devarch) +{ + return (devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH; +} + static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { + u32 devarch; + + devarch = readl_relaxed(drvdata->base + TRCDEVARCH); + if (!trace_unit_supported(devarch)) + return false; + *csa = CSDEV_ACCESS_IOMEM(drvdata->base); + drvdata->arch = devarch; + return true; }
@@ -713,7 +725,6 @@ static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata, static void etm4_init_arch_data(void *info) { u32 etmidr0; - u32 etmidr1; u32 etmidr2; u32 etmidr3; u32 etmidr4; @@ -784,14 +795,6 @@ static void etm4_init_arch_data(void *info) /* TSSIZE, bits[28:24] Global timestamp size field */ drvdata->ts_size = BMVAL(etmidr0, 24, 28);
- /* base architecture of trace unit */ - etmidr1 = etm4x_relaxed_read32(csa, TRCIDR1); - /* - * TRCARCHMIN, bits[7:4] architecture the minor version number - * TRCARCHMAJ, bits[11:8] architecture major versin number - */ - drvdata->arch = BMVAL(etmidr1, 4, 11); - /* maximum size of resources */ etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2); /* CIDSIZE, bits[9:5] Indicates the Context ID size */ @@ -1618,7 +1621,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) etm4_init_arch_data, &init_arg, 1)) dev_err(dev, "ETM arch init failed\n");
- if (etm4_arch_supported(drvdata->arch) == false) { + if (!drvdata->arch) { ret = -EINVAL; goto err_arch_supported; } @@ -1653,7 +1656,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
pm_runtime_put(&adev->dev); dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n", - drvdata->cpu, drvdata->arch >> 4, drvdata->arch & 0xf); + drvdata->cpu, etm_devarch_arch(drvdata->arch), + etm_devarch_rev(drvdata->arch));
if (boot_enable) { coresight_enable(drvdata->csdev); diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 277c22540db6..b217f16ad921 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -730,7 +730,7 @@ struct etmv4_save_state { * @spinlock: Only one at a time pls. * @mode: This tracer's mode, i.e sysFS, Perf or disabled. * @cpu: The cpu this component is affined to. - * @arch: ETM version number. + * @arch: ETM device architecture register. * @nr_pe: The number of processing entity available for tracing. * @nr_pe_cmp: The number of processing entity comparator inputs that are * available for tracing. @@ -793,7 +793,7 @@ struct etmv4_drvdata { spinlock_t spinlock; local_t mode; int cpu; - u8 arch; + u32 arch; u8 nr_pe; u8 nr_pe_cmp; u8 nr_addr_cmp;
Hi Suzuki
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
We have been using TRCIDR1 for detecting the ETM version. As we are about to discover the trace unit on a CPU, let us use a CoreSight architected register, instead of an ETM architected register for accurate detection on a CPU. e.g, a CPU might implement a custom trace unit, not an ETM.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 50 ++++++++++--------- drivers/hwtracing/coresight/coresight-etm4x.h | 4 +- 2 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 5880f105268f..0fce9fb12cff 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -61,6 +61,17 @@ struct etm_init_arg { struct csdev_access *csa; };
+static inline u8 etm_devarch_arch(u32 devarch) +{
return (devarch >> ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT) & 0xfUL;
+}
+static inline u8 etm_devarch_rev(u32 devarch) +{
return (devarch & ETM_DEVARCH_REVISION_MASK) >>
ETM_DEVARCH_REVISION_SHIFT;
+}
u64 etm4x_sysreg_read(struct csdev_access *csa, u32 offset, bool _relaxed, @@ -149,18 +160,6 @@ static void etm4_cs_unlock(struct etmv4_drvdata *drvdata, CS_UNLOCK(csa); }
-static bool etm4_arch_supported(u8 arch) -{
/* Mask out the minor version number */
switch (arch & 0xf0) {
case ETM_ARCH_V4:
break;
default:
return false;
}
return true;
-}
static int etm4_cpu_id(struct coresight_device *csdev) { struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -694,10 +693,23 @@ static void etm_detect_lock_status(struct etmv4_drvdata *drvdata, drvdata->os_lock_model = TRCOSLSR_OSM(os_lsr); }
+static inline bool trace_unit_supported(u32 devarch) +{
return (devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH;
+}
This is fine for system reg access - but imposes additional constraints on memory mapped devices that previously may have worked just by matching CID/PID. Can you be certain there are no devices out there that have omitted this register (it does have a present bit after all)
static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, struct csdev_access *csa) {
u32 devarch;
devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
if (!trace_unit_supported(devarch))
return false;
*csa = CSDEV_ACCESS_IOMEM(drvdata->base);
drvdata->arch = devarch;
return true;
}
@@ -713,7 +725,6 @@ static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata, static void etm4_init_arch_data(void *info)
The primary task of this routine is to read all the ID registers and set up the data in regards to resources etc. We should not be mixing in a secondary task of detection of a valid device.
{ u32 etmidr0;
u32 etmidr1; u32 etmidr2; u32 etmidr3; u32 etmidr4;
@@ -784,14 +795,6 @@ static void etm4_init_arch_data(void *info) /* TSSIZE, bits[28:24] Global timestamp size field */ drvdata->ts_size = BMVAL(etmidr0, 24, 28);
/* base architecture of trace unit */
etmidr1 = etm4x_relaxed_read32(csa, TRCIDR1);
/*
* TRCARCHMIN, bits[7:4] architecture the minor version number
* TRCARCHMAJ, bits[11:8] architecture major versin number
*/
drvdata->arch = BMVAL(etmidr1, 4, 11);
/* maximum size of resources */ etmidr2 = etm4x_relaxed_read32(csa, TRCIDR2); /* CIDSIZE, bits[9:5] Indicates the Context ID size */
@@ -1618,7 +1621,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) etm4_init_arch_data, &init_arg, 1)) dev_err(dev, "ETM arch init failed\n");
if (etm4_arch_supported(drvdata->arch) == false) {
if (!drvdata->arch) { ret = -EINVAL; goto err_arch_supported; }
@@ -1653,7 +1656,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
pm_runtime_put(&adev->dev); dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n",
drvdata->cpu, drvdata->arch >> 4, drvdata->arch & 0xf);
drvdata->cpu, etm_devarch_arch(drvdata->arch),
etm_devarch_rev(drvdata->arch)); if (boot_enable) { coresight_enable(drvdata->csdev);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h index 277c22540db6..b217f16ad921 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.h +++ b/drivers/hwtracing/coresight/coresight-etm4x.h @@ -730,7 +730,7 @@ struct etmv4_save_state {
- @spinlock: Only one at a time pls.
- @mode: This tracer's mode, i.e sysFS, Perf or disabled.
- @cpu: The cpu this component is affined to.
- @arch: ETM version number.
- @arch: ETM device architecture register.
- @nr_pe: The number of processing entity available for tracing.
- @nr_pe_cmp: The number of processing entity comparator inputs that are
available for tracing.
@@ -793,7 +793,7 @@ struct etmv4_drvdata { spinlock_t spinlock; local_t mode; int cpu;
u8 arch;
u32 arch; u8 nr_pe; u8 nr_pe_cmp; u8 nr_addr_cmp;
-- 2.24.1
Regards
Mike -- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
On 09/18/2020 04:35 PM, Mike Leach wrote:
Hi Suzuki
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
We have been using TRCIDR1 for detecting the ETM version. As we are about to discover the trace unit on a CPU, let us use a CoreSight architected register, instead of an ETM architected register for accurate detection on a CPU. e.g, a CPU might implement a custom trace unit, not an ETM.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
static int etm4_cpu_id(struct coresight_device *csdev) { struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); @@ -694,10 +693,23 @@ static void etm_detect_lock_status(struct etmv4_drvdata *drvdata, drvdata->os_lock_model = TRCOSLSR_OSM(os_lsr); }
+static inline bool trace_unit_supported(u32 devarch) +{
return (devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH;
+}
This is fine for system reg access - but imposes additional constraints on memory mapped devices that previously may have worked just by matching CID/PID. Can you be certain there are no devices out there that have omitted this register (it does have a present bit after all)
Very good point and I agree. I could restrict this to system instruction based devices and use the TRCIDR1 for
static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, struct csdev_access *csa) {
u32 devarch;
devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
if (!trace_unit_supported(devarch))
return false;
*csa = CSDEV_ACCESS_IOMEM(drvdata->base);
drvdata->arch = devarch;
}return true;
@@ -713,7 +725,6 @@ static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata, static void etm4_init_arch_data(void *info)
The primary task of this routine is to read all the ID registers and set up the data in regards to resources etc. We should not be mixing in a secondary task of detection of a valid device.
I agree that we have to read up the registers. However, for system instructions based devices, we shouldn't try to access random register space, if they are not ETM. Moreover, it kind of simplifies the logic, where you don't have to read up all the registers if this is not a supported device in the first place.
Or the other way around, I think the priority is to make sure we are dealing with a valid device we support, before we tread into reading the register space to avoid unknown side effects of the operations.
Thanks
Suzuki
ETM v4.4 onwards adds support for system instruction access to the ETM. Detect the support on an ETM and switch to using the mode when available.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.c | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 0fce9fb12cff..dc5ac171db35 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -693,11 +693,39 @@ static void etm_detect_lock_status(struct etmv4_drvdata *drvdata, drvdata->os_lock_model = TRCOSLSR_OSM(os_lsr); }
+static inline bool cpu_supports_sysreg_trace(void) +{ + u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1); + + return ((dfr0 >> ID_AA64DFR0_TRACEVER_SHIFT) & 0xfUL) > 0; +} + static inline bool trace_unit_supported(u32 devarch) { return (devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH; }
+static bool etm_init_sysreg_access(struct etmv4_drvdata *drvdata, + struct csdev_access *csa) +{ + u32 devarch; + + if (!cpu_supports_sysreg_trace()) + return false; + + devarch = read_etm4x_sysreg_const_offset(TRCDEVARCH); + if (!trace_unit_supported(devarch)) + return false; + *csa = (struct csdev_access) { + .io_mem = false, + .read = etm4x_sysreg_read, + .write = etm4x_sysreg_write, + }; + + drvdata->arch = devarch; + return true; +} + static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { @@ -716,6 +744,9 @@ static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { + if (etm_init_sysreg_access(drvdata, csa)) + return true; + if (drvdata->base) return etm_init_iomem_access(drvdata, csa);
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
ETM v4.4 onwards adds support for system instruction access to the ETM. Detect the support on an ETM and switch to using the mode when available.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 0fce9fb12cff..dc5ac171db35 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -693,11 +693,39 @@ static void etm_detect_lock_status(struct etmv4_drvdata *drvdata, drvdata->os_lock_model = TRCOSLSR_OSM(os_lsr); }
+static inline bool cpu_supports_sysreg_trace(void) +{
u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
return ((dfr0 >> ID_AA64DFR0_TRACEVER_SHIFT) & 0xfUL) > 0;
+}
This will be an issue if you have an aarch32 device (eg Cortex-A32 or similar, with ETM support but no aarch64)
static inline bool trace_unit_supported(u32 devarch) { return (devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH; }
+static bool etm_init_sysreg_access(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
+{
u32 devarch;
if (!cpu_supports_sysreg_trace())
return false;
devarch = read_etm4x_sysreg_const_offset(TRCDEVARCH);
if (!trace_unit_supported(devarch))
return false;
*csa = (struct csdev_access) {
.io_mem = false,
.read = etm4x_sysreg_read,
.write = etm4x_sysreg_write,
};
drvdata->arch = devarch;
return true;
+}
static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, struct csdev_access *csa) { @@ -716,6 +744,9 @@ static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata, struct csdev_access *csa) {
if (etm_init_sysreg_access(drvdata, csa))
Don't think we should enforce system instruction access if the device tree has defined memory access. The driver cannot possibly know if this is a mistake or deliberate (e.g. test / implementation bug fix).> + return true;
if (drvdata->base) return etm_init_iomem_access(drvdata, csa);
-- 2.24.1
The device tree bindings define the access support intended - and there is access specific probing. i.e. the next patch splits amba (mem access) / platform (sys access) driver probes, followed by the common probe section. The register / memory access support used should be made there, and the detection of a compatible device for the register access i.e. check TRCDEVARCH should be in the platform probe path too - possibly simplifying things and ensuring the common code changes are reduced.
Regards
Mike
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
On 09/18/2020 04:35 PM, Mike Leach wrote:
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
ETM v4.4 onwards adds support for system instruction access to the ETM. Detect the support on an ETM and switch to using the mode when available.
Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 0fce9fb12cff..dc5ac171db35 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -693,11 +693,39 @@ static void etm_detect_lock_status(struct etmv4_drvdata *drvdata, drvdata->os_lock_model = TRCOSLSR_OSM(os_lsr); }
+static inline bool cpu_supports_sysreg_trace(void) +{
u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
return ((dfr0 >> ID_AA64DFR0_TRACEVER_SHIFT) & 0xfUL) > 0;
+}
This will be an issue if you have an aarch32 device (eg Cortex-A32 or similar, with ETM support but no aarch64)
Agreed and in fact this was part of the header file in my initial versions. I could move it back there. However, the ETM4x even without this series doesn't support aarch32. The compilation would fail for various reasons (e.g, readq()).
static inline bool trace_unit_supported(u32 devarch) { return (devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH; }
+static bool etm_init_sysreg_access(struct etmv4_drvdata *drvdata,
struct csdev_access *csa)
+{
u32 devarch;
if (!cpu_supports_sysreg_trace())
return false;
devarch = read_etm4x_sysreg_const_offset(TRCDEVARCH);
if (!trace_unit_supported(devarch))
return false;
*csa = (struct csdev_access) {
.io_mem = false,
.read = etm4x_sysreg_read,
.write = etm4x_sysreg_write,
};
drvdata->arch = devarch;
return true;
+}
- static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, struct csdev_access *csa) {
@@ -716,6 +744,9 @@ static bool etm_init_iomem_access(struct etmv4_drvdata *drvdata, static bool etm_init_csdev_access(struct etmv4_drvdata *drvdata, struct csdev_access *csa) {
if (etm_init_sysreg_access(drvdata, csa))
Don't think we should enforce system instruction access if the device tree has defined memory access. The driver cannot possibly know if this is a mistake or deliberate (e.g. test / implementation bug fix).>
return true;
Agreed, will fix it.
if (drvdata->base) return etm_init_iomem_access(drvdata, csa);
-- 2.24.1
The device tree bindings define the access support intended - and there is access specific probing. i.e. the next patch splits amba (mem access) / platform (sys access) driver probes, followed by the common probe section. The register / memory access support used should be made there, and the detection of a compatible device for the register access i.e. check TRCDEVARCH should be in the platform probe path too
- possibly simplifying things and ensuring the common code changes are
reduced.
I will address this in the next version. I believe we could work around the problem of missing TRCDEVARCH on older platforms.
Thanks a lot for the review !
Suzuki
CoreSight ETM with system register access may not have a memory mapped i/o access. Refactor the ETM specific probing into a common routine to allow reusing the code for such ETMs.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.c | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index dc5ac171db35..7d5f942c2108 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1596,14 +1596,11 @@ static void __init etm4_pm_clear(void) } }
-static int etm4_probe(struct amba_device *adev, const struct amba_id *id) +static int etm4_probe(struct device *dev, void __iomem *base) { int ret; - void __iomem *base; - struct device *dev = &adev->dev; struct coresight_platform_data *pdata = NULL; struct etmv4_drvdata *drvdata; - struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; struct etm_init_arg init_arg = { 0 };
@@ -1627,11 +1624,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) if (fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up")) drvdata->skip_power_up = true;
- /* Validity for the resource is already checked by the AMBA core */ - base = devm_ioremap_resource(dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); - drvdata->base = base;
spin_lock_init(&drvdata->spinlock); @@ -1665,7 +1657,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) ret = PTR_ERR(pdata); goto err_arch_supported; } - adev->dev.platform_data = pdata; + dev->platform_data = pdata;
desc.type = CORESIGHT_DEV_TYPE_SOURCE; desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC; @@ -1685,7 +1677,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) goto err_arch_supported; }
- pm_runtime_put(&adev->dev); dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n", drvdata->cpu, etm_devarch_arch(drvdata->arch), etm_devarch_rev(drvdata->arch)); @@ -1702,6 +1693,25 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) return ret; }
+static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id) +{ + void __iomem *base; + struct device *dev = &adev->dev; + struct resource *res = &adev->res; + int ret; + + /* Validity for the resource is already checked by the AMBA core */ + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + ret = etm4_probe(dev, base); + if (!ret) + pm_runtime_put(&adev->dev); + + return ret; +} + static struct amba_cs_uci_id uci_id_etm4[] = { { /* ETMv4 UCI data */ @@ -1730,12 +1740,12 @@ static const struct amba_id etm4_ids[] = { {}, };
-static struct amba_driver etm4x_driver = { +static struct amba_driver etm4x_amba_driver = { .drv = { .name = "coresight-etm4x", .suppress_bind_attrs = true, }, - .probe = etm4_probe, + .probe = etm4_probe_amba, .id_table = etm4_ids, };
@@ -1749,7 +1759,7 @@ static int __init etm4x_init(void) if (ret) return ret;
- ret = amba_driver_register(&etm4x_driver); + ret = amba_driver_register(&etm4x_amba_driver); if (ret) { pr_err("Error registering etm4x driver\n"); etm4_pm_clear();
Reviewed-by: Mike Leach mike.leach@linaro.org
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
CoreSight ETM with system register access may not have a memory mapped i/o access. Refactor the ETM specific probing into a common routine to allow reusing the code for such ETMs.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index dc5ac171db35..7d5f942c2108 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1596,14 +1596,11 @@ static void __init etm4_pm_clear(void) } }
-static int etm4_probe(struct amba_device *adev, const struct amba_id *id) +static int etm4_probe(struct device *dev, void __iomem *base) { int ret;
void __iomem *base;
struct device *dev = &adev->dev; struct coresight_platform_data *pdata = NULL; struct etmv4_drvdata *drvdata;
struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; struct etm_init_arg init_arg = { 0 };
@@ -1627,11 +1624,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) if (fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up")) drvdata->skip_power_up = true;
/* Validity for the resource is already checked by the AMBA core */
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
drvdata->base = base; spin_lock_init(&drvdata->spinlock);
@@ -1665,7 +1657,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) ret = PTR_ERR(pdata); goto err_arch_supported; }
adev->dev.platform_data = pdata;
dev->platform_data = pdata; desc.type = CORESIGHT_DEV_TYPE_SOURCE; desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
@@ -1685,7 +1677,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) goto err_arch_supported; }
pm_runtime_put(&adev->dev); dev_info(&drvdata->csdev->dev, "CPU%d: ETM v%d.%d initialized\n", drvdata->cpu, etm_devarch_arch(drvdata->arch), etm_devarch_rev(drvdata->arch));
@@ -1702,6 +1693,25 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) return ret; }
+static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id) +{
void __iomem *base;
struct device *dev = &adev->dev;
struct resource *res = &adev->res;
int ret;
/* Validity for the resource is already checked by the AMBA core */
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
ret = etm4_probe(dev, base);
if (!ret)
pm_runtime_put(&adev->dev);
return ret;
+}
static struct amba_cs_uci_id uci_id_etm4[] = { { /* ETMv4 UCI data */ @@ -1730,12 +1740,12 @@ static const struct amba_id etm4_ids[] = { {}, };
-static struct amba_driver etm4x_driver = { +static struct amba_driver etm4x_amba_driver = { .drv = { .name = "coresight-etm4x", .suppress_bind_attrs = true, },
.probe = etm4_probe,
.probe = etm4_probe_amba, .id_table = etm4_ids,
};
@@ -1749,7 +1759,7 @@ static int __init etm4x_init(void) if (ret) return ret;
ret = amba_driver_register(&etm4x_driver);
ret = amba_driver_register(&etm4x_amba_driver); if (ret) { pr_err("Error registering etm4x driver\n"); etm4_pm_clear();
-- 2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Add support for devices with system instruction access only. They don't have a memory mapped interface and thus are not AMBA devices.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- drivers/hwtracing/coresight/coresight-etm4x.c | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 7d5f942c2108..212713ffa37e 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -26,6 +26,7 @@ #include <linux/seq_file.h> #include <linux/uaccess.h> #include <linux/perf_event.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/property.h> #include <asm/sections.h> @@ -1712,6 +1713,20 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id) return ret; }
+static int etm4_probe_platform_dev(struct platform_device *pdev) +{ + int ret; + + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + + ret = etm4_probe(&pdev->dev, NULL); + + pm_runtime_put(&pdev->dev); + return ret; +} + static struct amba_cs_uci_id uci_id_etm4[] = { { /* ETMv4 UCI data */ @@ -1749,6 +1764,20 @@ static struct amba_driver etm4x_amba_driver = { .id_table = etm4_ids, };
+static const struct of_device_id etm4_4_match[] = { + { .compatible = "arm,coresight-etm-v4.4" }, + {} +}; + +static struct platform_driver etm4_platform_driver = { + .probe = etm4_probe_platform_dev, + .driver = { + .name = "coresight-etm4x", + .of_match_table = etm4_4_match, + .suppress_bind_attrs = true, + }, +}; + static int __init etm4x_init(void) { int ret; @@ -1761,10 +1790,19 @@ static int __init etm4x_init(void)
ret = amba_driver_register(&etm4x_amba_driver); if (ret) { - pr_err("Error registering etm4x driver\n"); - etm4_pm_clear(); + pr_err("Error registering etm4x AMBA driver\n"); + goto clear_pm; }
+ ret = platform_driver_register(&etm4_platform_driver); + if (!ret) + return 0; + + pr_err("Error registering etm4x platform driver\n"); + amba_driver_unregister(&etm4x_amba_driver); + +clear_pm: + etm4_pm_clear(); return ret; } device_initcall(etm4x_init);
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Add support for devices with system instruction access only. They don't have a memory mapped interface and thus are not AMBA devices.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 7d5f942c2108..212713ffa37e 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -26,6 +26,7 @@ #include <linux/seq_file.h> #include <linux/uaccess.h> #include <linux/perf_event.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/property.h> #include <asm/sections.h> @@ -1712,6 +1713,20 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id) return ret; }
+static int etm4_probe_platform_dev(struct platform_device *pdev) +{
int ret;
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
Right about here is where I would expect the sysreg access to TRCDEVARCH etc, to determine if this is an ETM device that can be supported by the driver. This matches approximately the similar ID table checks that the AMBA driver did to ensure a valid device match. This logically separates "is this a device we support" from "what features does this supported device have"
ret = etm4_probe(&pdev->dev, NULL);
pm_runtime_put(&pdev->dev);
return ret;
+}
static struct amba_cs_uci_id uci_id_etm4[] = { { /* ETMv4 UCI data */ @@ -1749,6 +1764,20 @@ static struct amba_driver etm4x_amba_driver = { .id_table = etm4_ids, };
+static const struct of_device_id etm4_4_match[] = {
{ .compatible = "arm,coresight-etm-v4.4" },
{}
+};
+static struct platform_driver etm4_platform_driver = {
.probe = etm4_probe_platform_dev,
.driver = {
.name = "coresight-etm4x",
.of_match_table = etm4_4_match,
.suppress_bind_attrs = true,
},
+};
static int __init etm4x_init(void) { int ret; @@ -1761,10 +1790,19 @@ static int __init etm4x_init(void)
ret = amba_driver_register(&etm4x_amba_driver); if (ret) {
pr_err("Error registering etm4x driver\n");
etm4_pm_clear();
pr_err("Error registering etm4x AMBA driver\n");
goto clear_pm; }
ret = platform_driver_register(&etm4_platform_driver);
if (!ret)
return 0;
pr_err("Error registering etm4x platform driver\n");
amba_driver_unregister(&etm4x_amba_driver);
+clear_pm:
etm4_pm_clear(); return ret;
} device_initcall(etm4x_init); -- 2.24.1
Regards
Mike
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Hi Mike
On 09/18/2020 04:35 PM, Mike Leach wrote:
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Add support for devices with system instruction access only. They don't have a memory mapped interface and thus are not AMBA devices.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 7d5f942c2108..212713ffa37e 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -26,6 +26,7 @@ #include <linux/seq_file.h> #include <linux/uaccess.h> #include <linux/perf_event.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/property.h> #include <asm/sections.h> @@ -1712,6 +1713,20 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id) return ret; }
+static int etm4_probe_platform_dev(struct platform_device *pdev) +{
int ret;
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
Right about here is where I would expect the sysreg access to TRCDEVARCH etc, to determine if this is an ETM device that can be supported by the driver. This matches approximately the similar ID table checks that the AMBA driver did to ensure a valid device match.
The problem is, we have to do this on the target CPU and later do another one for feature check.
This logically separates "is this a device we support" from "what features does this supported device have"
While I understand the logical argument, it doesn't buy us much. Even now we do an additional check on the supported architecture in the etm4x_probe() anyway and reject the unsupported CPUs there. The only change here is we move the supported architecture check in to the etm4_init_arch_data() and stop the hard work if it is not supported.
I would prefer to keep the current method if possible, while cleaning up the detection of the supported (old) devices as agreed in the other patch.
Cheers Suzuki
Hi Suzuki,
On Wed, 23 Sep 2020 at 12:47, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Hi Mike
On 09/18/2020 04:35 PM, Mike Leach wrote:
Hi Suzuki,
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Add support for devices with system instruction access only. They don't have a memory mapped interface and thus are not AMBA devices.
Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
drivers/hwtracing/coresight/coresight-etm4x.c | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 7d5f942c2108..212713ffa37e 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -26,6 +26,7 @@ #include <linux/seq_file.h> #include <linux/uaccess.h> #include <linux/perf_event.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/property.h> #include <asm/sections.h> @@ -1712,6 +1713,20 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id) return ret; }
+static int etm4_probe_platform_dev(struct platform_device *pdev) +{
int ret;
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
Right about here is where I would expect the sysreg access to TRCDEVARCH etc, to determine if this is an ETM device that can be supported by the driver. This matches approximately the similar ID table checks that the AMBA driver did to ensure a valid device match.
The problem is, we have to do this on the target CPU and later do another one for feature check.
This logically separates "is this a device we support" from "what features does this supported device have"
The additional point is that it also keeps the register access specific code encapsulated in the register access specific area. The whole point of the access abstraction is that the common code just works. Is it not better that the access decision is made as early as possible and the access abstraction is set up, then the more code is common and maintenance is easier going forwards?
While I understand the logical argument, it doesn't buy us much. Even now we do an additional check on the supported architecture in the etm4x_probe() anyway and reject the unsupported CPUs there.
I do question the value of that check. It's been around since the start of the driver, but perhaps has outlived its usefulness.
Even in the AMBA memory mapped case, by the time we get there, we have matched the device based on supplied part numbers & binding information in the device tree, so checking 4 bits (major version number) out of a register does seem curious! If we have somehow got a bunch of other things wrong, there is a 1 in 16 chance that this check will fail too with a false positive.
Obviously I can see why you wouldn't want to rely on just that to validate the component type for register access - DEVARCH is far better for that use case.
The etmv3 version is a little more interesting - it checks 8 bits, both maj and min versions, with specific checks on 3.3, 3.5, 1.0 and 1.1 (pft),
The remainder of the coresight drivers simply trust the part number detection mechanisms. Would it not be more consistent to do the same for ETMv4 as well?
The only change here is we move the supported architecture check in to the etm4_init_arch_data() and stop the hard work if it is not supported.
I would prefer to keep the current method if possible, while cleaning up the detection of the supported (old) devices as agreed in the other patch.
Cheers Suzuki
Cheers
Mike
Document the bindings for ETMv4.4 and later with only system register access.
Cc: devicetree@vger.kernel.org Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Reviewed-by: Rob Herring robh@kernel.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com --- Documentation/devicetree/bindings/arm/coresight.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt index d711676b4a51..cfe47bdda728 100644 --- a/Documentation/devicetree/bindings/arm/coresight.txt +++ b/Documentation/devicetree/bindings/arm/coresight.txt @@ -34,9 +34,13 @@ its hardware characteristcs. Program Flow Trace Macrocell: "arm,coresight-etm3x", "arm,primecell";
- - Embedded Trace Macrocell (version 4.x): + - Embedded Trace Macrocell (version 4.x), with memory mapped access. "arm,coresight-etm4x", "arm,primecell";
+ - Embedded Trace Macrocell (version 4.4 and later) with system + register access only. + "arm,coresight-etm-v4.4"; + - Coresight programmable Replicator : "arm,coresight-dynamic-replicator", "arm,primecell";
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Document the bindings for ETMv4.4 and later with only system register access.
Cc: devicetree@vger.kernel.org Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Reviewed-by: Rob Herring robh@kernel.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
Documentation/devicetree/bindings/arm/coresight.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt index d711676b4a51..cfe47bdda728 100644 --- a/Documentation/devicetree/bindings/arm/coresight.txt +++ b/Documentation/devicetree/bindings/arm/coresight.txt @@ -34,9 +34,13 @@ its hardware characteristcs. Program Flow Trace Macrocell: "arm,coresight-etm3x", "arm,primecell";
- Embedded Trace Macrocell (version 4.x):
- Embedded Trace Macrocell (version 4.x), with memory mapped access. "arm,coresight-etm4x", "arm,primecell";
- Embedded Trace Macrocell (version 4.4 and later) with system
register access only.
"arm,coresight-etm-v4.4";
Any version of ETM can implement register access - including those pre ETM 4.4. Perhaps the new name should simply reflect sys reg access rather than a version.
Given that the two compatibility strings should be mutually exclusive for a given device, should the bindings doc (or at least the etm4x component part) be re-written into the .yaml format so that this can be enforced?
Regards
Mike
- Coresight programmable Replicator : "arm,coresight-dynamic-replicator", "arm,primecell";
-- 2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
On 09/18/2020 04:35 PM, Mike Leach wrote:
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Document the bindings for ETMv4.4 and later with only system register access.
Cc: devicetree@vger.kernel.org Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Reviewed-by: Rob Herring robh@kernel.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
Documentation/devicetree/bindings/arm/coresight.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt index d711676b4a51..cfe47bdda728 100644 --- a/Documentation/devicetree/bindings/arm/coresight.txt +++ b/Documentation/devicetree/bindings/arm/coresight.txt @@ -34,9 +34,13 @@ its hardware characteristcs. Program Flow Trace Macrocell: "arm,coresight-etm3x", "arm,primecell";
- Embedded Trace Macrocell (version 4.x):
- Embedded Trace Macrocell (version 4.x), with memory mapped access. "arm,coresight-etm4x", "arm,primecell";
- Embedded Trace Macrocell (version 4.4 and later) with system
register access only.
"arm,coresight-etm-v4.4";
Any version of ETM can implement register access - including those pre ETM 4.4. Perhaps the new name should simply reflect sys reg access rather than a version.
You're right. I got it confused with the v8.4 SelfHosted Extensions, which mandates the sysreg access and makes the mem I/O obsolete. How about :
"arm,coresight-etm4x-sysreg" ?
Given that the two compatibility strings should be mutually exclusive for a given device, should the bindings doc (or at least the etm4x component part) be re-written into the .yaml format so that this can be enforced?
I will take a look, haven't played with the yaml.
Thanks for the review !
Suzuki
Hi suzuki,
On Thu, 24 Sep 2020 at 10:43, Suzuki K Poulose suzuki.poulose@arm.com wrote:
On 09/18/2020 04:35 PM, Mike Leach wrote:
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Document the bindings for ETMv4.4 and later with only system register access.
Cc: devicetree@vger.kernel.org Cc: Mathieu Poirier mathieu.poirier@linaro.org Cc: Mike Leach mike.leach@linaro.org Reviewed-by: Rob Herring robh@kernel.org Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com
Documentation/devicetree/bindings/arm/coresight.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt index d711676b4a51..cfe47bdda728 100644 --- a/Documentation/devicetree/bindings/arm/coresight.txt +++ b/Documentation/devicetree/bindings/arm/coresight.txt @@ -34,9 +34,13 @@ its hardware characteristcs. Program Flow Trace Macrocell: "arm,coresight-etm3x", "arm,primecell";
- Embedded Trace Macrocell (version 4.x):
- Embedded Trace Macrocell (version 4.x), with memory mapped access. "arm,coresight-etm4x", "arm,primecell";
- Embedded Trace Macrocell (version 4.4 and later) with system
register access only.
"arm,coresight-etm-v4.4";
Any version of ETM can implement register access - including those pre ETM 4.4. Perhaps the new name should simply reflect sys reg access rather than a version.
You're right. I got it confused with the v8.4 SelfHosted Extensions, which mandates the sysreg access and makes the mem I/O obsolete. How about :
"arm,coresight-etm4x-sysreg" ?
Seems reasonable. Perhaps ensure that the accompanying comment mentions that this is aarch64 access (to cover the unlikely event that some outlier implementation does come along with v8 aarch32 + ETMv4 + sysreg access!)
Given that the two compatibility strings should be mutually exclusive for a given device, should the bindings doc (or at least the etm4x component part) be re-written into the .yaml format so that this can be enforced?
I will take a look, haven't played with the yaml.
I used it to describe the CTI bindings as these were brand new. Reasonably straight forwards - there are plenty of examples and the checking tools are pretty good.
Regards
Mike
Thanks for the review !
Suzuki
Hi Suzuki,
I've looked at the set and have only one real gripe - the implementation and timing of component detection on the sysreg path. I've summarised my thoughts here, but as the changes are found across multiple patches I may well have repeated myself a little in the individual places.
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
CoreSight ETMv4.4 introduced system instructions for accessing the ETM. This also implies that they may not be on the amba bus.
System instructions have always been an option - but we have never supported them up to now. In fact both memory access and system instructions can live side by side - but the driver really needs to choose just one! What did happen is that a PE that supports Arm Trace 8.4 mandates ETM 4.4, and ETM 4.4 mandates system instruction access for PEs with Arm Trace 8.4, and deprecates memory access.
But there is nothing to stop other variants having the system instruction interface. So there is no need to describe this as a purely 4.4. onwards support - it will support any version of the ETM that has sysreg access.
The spec permits aarch32 / armv7 register access via CP14 - but I assume this is omitted deliberately & not intended to be supported at this time.
Right now all the CoreSight components are accessed via memory map. Also, we have some common routines in coresight generic code driver (e.g, CS_LOCK, claim/disclaim), which assume the mmio. In order to preserve the generic algorithms at a single place and to allow dynamic switch for ETMs, this series introduces an abstraction layer for accessing a coresight device. It is designed such that the mmio access are fast tracked (i.e, without an indirect function call).
This will also help us to get rid of the driver+attribute specific sysfs show/store routines and replace them with a single routine to access a given register offset (which can be embedded in the dev_ext_attribute). This is not currently implemented in the series, but can be achieved.
Further we switch the generic routines to work with the abstraction. With this in place, we refactor the etm4x code a bit to allow for supporting the system instructions with very little new code. The changes also switch to using the system instructions by default even when we may have an MMIO.
We use TRCDEVARCH for the detection of the ETM component, which is a standard register as per CoreSight architecture, rather than the etm specific id register TRCIDR3. This is for making sure that we are able to detect the ETM via system instructions accurately, when the the trace unit could be anything (etm or a custom trace unit).
I'm assuming you mean TRCIDR1 here -- which in part, defines the etm architecture version. TRCIDR3 does something else entirely. Not sure I agree with this though - the driver is designed to match the ETM spec so there is no problem with using TRCIDR1 to spot functional variants according to ETM version,
The etm4_init_arch_data() function is not about detecting the presence of an ETMv4 component, but about exploring the capabilities it has. We check 4 bits of the version as a sanity check, but at this point we should be pretty sure we are dealing with an ETM of some kind.
TRCDEVARCH is already used for detection in the AMBA matching code - assuming the table includes the optional CoreSIght UCI. I would imagine that similar detection needs to go on for instruction access - but once we have detected an ETM, then ETM architected registers are sufficient. If the device is not an ETM then it should be detected and rejected early - and the bindings examined to determine why this driver was attached!
The act of adding in a check against TRCDEVARCH as part of the etm4_init_arch_data() function adds new and hidden checks to AMBA devices where it was sufficient to have an entry in the probe match table before. Most recent additions include the UCI matching, but older ones don't. I am concerned that this changes may trip up older existing implementations which for some reason may not have TRCDEVCARCH, or have set it to not present.
For this reason, I beleive that the TRCDEVARCH check for the sys reg access should occur on the sysreg specific probe - balancing what happens on the AMBA side. That way the common code remains common. Further the setup of the CSA for the device can happen immediately in the common etm_probe() function, based on *base being NULL or not, rather than as a side effect of the etm4_init_arch_data() call.
Regards
Mike
The series has been mildly tested on a model. I would really appreciate any testing on real hardware.
Applies on coresight/next
Changes since V1:
- Flip the switch for iomem from no_iomem to io_mem in csdev_access.
- Split patches for claim/disclaim and CS_LOCK/UNLOCK conversions.
- Move device access initialisation for etm4x to the target CPU
- Cleanup secure exception level mask handling.
- Switch to use TRCDEVARCH for ETM component discovery. This is for making
- Check the availability of OS/Software Locks before using them.
Suzuki K Poulose (19): coresight: Introduce device access abstraction coresight: tpiu: Prepare for using coresight device access abstraction coresight: Convert coresight_timeout to use access abstraction coresight: Convert claim/disclaim operations to use access wrappers coresight: Use device access layer for Software lock/unlock operations coresight: etm4x: Always read the registers on the host CPU coresight: etm4x: Convert all register accesses coresight: etm4x: Add commentary on the registers coresight: etm4x: Add sysreg access helpers coresight: etm4x: Define DEVARCH register fields coresight: etm4x: Check for OS and Software Lock coresight: etm4x: Cleanup secure exception level masks coresight: etm4x: Clean up exception level masks coresight: etm4x: Detect access early on the target CPU coresight: etm4x: Use TRCDEVARCH for component discovery coresight: etm4x: Detect system instructions support coresight: etm4x: Refactor probing routine coresight: etm4x: Add support for sysreg only devices dts: bindings: coresight: ETMv4.4 system register access only units
.../devicetree/bindings/arm/coresight.txt | 6 +- drivers/hwtracing/coresight/coresight-catu.c | 24 +- .../hwtracing/coresight/coresight-cpu-debug.c | 22 +- .../hwtracing/coresight/coresight-cti-sysfs.c | 5 +- drivers/hwtracing/coresight/coresight-cti.c | 34 +- drivers/hwtracing/coresight/coresight-etb10.c | 29 +- .../coresight/coresight-etm3x-sysfs.c | 10 +- drivers/hwtracing/coresight/coresight-etm3x.c | 35 +- .../coresight/coresight-etm4x-sysfs.c | 44 +- drivers/hwtracing/coresight/coresight-etm4x.c | 716 +++++++++++------- drivers/hwtracing/coresight/coresight-etm4x.h | 440 ++++++++++- .../hwtracing/coresight/coresight-funnel.c | 22 +- drivers/hwtracing/coresight/coresight-priv.h | 9 +- .../coresight/coresight-replicator.c | 31 +- drivers/hwtracing/coresight/coresight-stm.c | 50 +- .../hwtracing/coresight/coresight-tmc-etf.c | 38 +- .../hwtracing/coresight/coresight-tmc-etr.c | 20 +- drivers/hwtracing/coresight/coresight-tmc.c | 16 +- drivers/hwtracing/coresight/coresight-tpiu.c | 32 +- drivers/hwtracing/coresight/coresight.c | 130 +++- include/linux/coresight.h | 230 +++++- 21 files changed, 1449 insertions(+), 494 deletions(-)
-- 2.24.1
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK
Hi Mike,
First of all, thank you so much for your in depth review. Please find my comments inline.
On 09/18/2020 04:33 PM, Mike Leach wrote:
Hi Suzuki,
I've looked at the set and have only one real gripe - the implementation and timing of component detection on the sysreg path. I've summarised my thoughts here, but as the changes are found across multiple patches I may well have repeated myself a little in the individual places.
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
CoreSight ETMv4.4 introduced system instructions for accessing the ETM. This also implies that they may not be on the amba bus.
System instructions have always been an option - but we have never supported them up to now. In fact both memory access and system instructions can live side by side - but the driver really needs to choose just one! What did happen is that a PE that supports Arm Trace 8.4 mandates ETM 4.4, and ETM 4.4 mandates system instruction access for PEs with Arm Trace 8.4, and deprecates memory access.
But there is nothing to stop other variants having the system instruction interface. So there is no need to describe this as a purely 4.4. onwards support - it will support any version of the ETM that has sysreg access.
Correct, I agree, and will change this.
The spec permits aarch32 / armv7 register access via CP14 - but I assume this is omitted deliberately & not intended to be supported at this time.
Yes, because the ETMv4 driver doesn't support arm32 bit at all. We could definitely add this in the future. I will add it to the commit description.
Right now all the CoreSight components are accessed via memory map. Also, we have some common routines in coresight generic code driver (e.g, CS_LOCK, claim/disclaim), which assume the mmio. In order to preserve the generic algorithms at a single place and to allow dynamic switch for ETMs, this series introduces an abstraction layer for accessing a coresight device. It is designed such that the mmio access are fast tracked (i.e, without an indirect function call).
This will also help us to get rid of the driver+attribute specific sysfs show/store routines and replace them with a single routine to access a given register offset (which can be embedded in the dev_ext_attribute). This is not currently implemented in the series, but can be achieved.
Further we switch the generic routines to work with the abstraction. With this in place, we refactor the etm4x code a bit to allow for supporting the system instructions with very little new code. The changes also switch to using the system instructions by default even when we may have an MMIO.
We use TRCDEVARCH for the detection of the ETM component, which is a standard register as per CoreSight architecture, rather than the etm specific id register TRCIDR3. This is for making sure that we are able to detect the ETM via system instructions accurately, when the the trace unit could be anything (etm or a custom trace unit).
I'm assuming you mean TRCIDR1 here -- which in part, defines the etm architecture version. TRCIDR3 does something else entirely.
Yes, definitely, it is a mistake on my side, generated from staring at both of them TRCIDR1 and TRCIDR3 (for the masks).
Not sure I agree with this though - the driver is designed to match the ETM spec so there is no problem with using TRCIDR1 to spot functional variants according to ETM version,
Correct. But for a system instruction based trace unit, we can't trust just the bindings and must use a CoreSight architected register to do the basic detection. Also, I am planning to add support the Future Architectures for the processor trace [0] with the ETM driver, which mandates the use of TRCDEVARCH for the trace version. So, this is more of
The etm4_init_arch_data() function is not about detecting the presence of an ETMv4 component, but about exploring the capabilities it has. We check 4 bits of the version as a sanity check, but at this point we should be pretty sure we are dealing with an ETM of some kind.
TRCDEVARCH is already used for detection in the AMBA matching code - assuming the table includes the optional CoreSIght UCI. I would imagine that similar detection needs to go on for instruction access - but once we have detected an ETM, then ETM architected registers are sufficient. If the device is not an ETM then it should be detected and rejected early - and the bindings examined to determine why this driver was attached!
I agree with the fact that we should check the device for a supported type at the earliest and must not trust the bindings. With the AMBA based devices we have the early check as mentioned above via the PIDs and the UCI (where available). But where the UCI is not listed, these will be caught by the additional checks on the TRCIDR1 fields. e.g, CTI could have the same PID as an ETM4 and without the UCI field, the driver could assume that an ETM is CTI if the firmware was incorrect.
The act of adding in a check against TRCDEVARCH as part of the etm4_init_arch_data() function adds new and hidden checks to AMBA devices where it was sufficient to have an entry in the probe match table before. Most recent additions include the UCI matching, but older ones don't. I am concerned that this changes may trip up older existing implementations which for some reason may not have TRCDEVCARCH, or have set it to not present.
For the records, ETMv4.0 revision A, says, the PRESENT bit is always Read As One (RAO). So, if they don't implement it or have set to 0, that means that they are broken. But, we could gracefully handle it if the PRESENT bit is 0 and fold back to TRCIDR1.
For this reason, I beleive that the TRCDEVARCH check for the sys reg access should occur on the sysreg specific probe - balancing what happens on the AMBA side. That way the common code remains common.
To make the current situation clear, for those who have not looked at the series, here is the summary :
1) AMBA driver checks the PIDs to match a device to known ETMv4. Note that CTIs could share the same PIDs and thus we added additional check on the UCI (which is TRCDEVARCH) field for some of the ETMs.
2) The ETM4 driver assumes that the component is ETMv4 and calls etmv4_init_arch_data() and probes the ETM4 for features, filling in drvdata, including the TRCIDR1. Please note that, at this point there is no guarantee that the unit is indeed ETMv4, if the UCI check (TRCDEVARCH) has not been performed. So, we are possibly treading into wild land here (at least on bring up).
3) The etm4_probe() confirms that the ETM4 architecture is supported by checking the TRCIDR1 fields (stored in drvdata->arch from step (2)). This check is important (at least for bring up), because if the UCI check is not added for the component, a CTI could be mistaken for an ETM with AMBA devices.
Fact : TRCDEVARCH must be implemented and represent that the component is ETMv4 (this is the basis of UCI check) since ETMv4.0 specification.
For the system instructions based devices, we have : 1) Device tree compatible to advertise the presence of a trace unit on a CPU. (no PID checks, this is good, because you don't have to add an entry for a new CPU to be supported upstream, as long as it is compliant with the ETMv4).
2) To confirm that the CPU tracing unit is ETMv4 compatible, we need to use CoreSight architected register, TRCDEVARCH (the same as UCI). This is because TRCIDR1 may not be what is expected if the Trace unit is not ETMv4, since the encoding is ETM specific. And this must be performed on the host CPU (just like etm4_init_arch_data).
With this series:
* AMBA devices pass through the PID check as usual. But the sysreg devices jumps straight to etm4_init_arch_data() via common etm4_probe.
* etm4_init_arch_data() will verify that the component is ETMv4 by verifying the TRCDEVARCH for all ETMs (both AMBA and system instructions), before poking the features. This will avoid having to do another round of smp_func_call() in etm4 sysreg probe code. - Note: As per Mike's suggestion, this can be further relaxed to check TRCIDR1 for AMBA devices, iff TRCDEVARCH is marked absent for supporting any wild broken implementations out there (I prefer to add a pr_warn_once() for such cases, so that we know such units).
Further the setup of the CSA for the device can happen immediately in the common etm_probe() function, based on *base being NULL or not,
For now, yes. But with the additional changes for supporting [0], this may not. As we need to really see if we have an ETMv4.x or a future unit which has slightly different register list.
rather than as a side effect of the etm4_init_arch_data() call.
[0] https://developer.arm.com/docs/ddi0601/latest , See TRCIDR1
Kind regards Suzuki
Hi Suzuki,
On Fri, 25 Sep 2020 at 10:50, Suzuki K Poulose suzuki.poulose@arm.com wrote:
Hi Mike,
First of all, thank you so much for your in depth review. Please find my comments inline.
On 09/18/2020 04:33 PM, Mike Leach wrote:
Hi Suzuki,
I've looked at the set and have only one real gripe - the implementation and timing of component detection on the sysreg path. I've summarised my thoughts here, but as the changes are found across multiple patches I may well have repeated myself a little in the individual places.
On Fri, 11 Sep 2020 at 09:41, Suzuki K Poulose suzuki.poulose@arm.com wrote:
CoreSight ETMv4.4 introduced system instructions for accessing the ETM. This also implies that they may not be on the amba bus.
System instructions have always been an option - but we have never supported them up to now. In fact both memory access and system instructions can live side by side - but the driver really needs to choose just one! What did happen is that a PE that supports Arm Trace 8.4 mandates ETM 4.4, and ETM 4.4 mandates system instruction access for PEs with Arm Trace 8.4, and deprecates memory access.
But there is nothing to stop other variants having the system instruction interface. So there is no need to describe this as a purely 4.4. onwards support - it will support any version of the ETM that has sysreg access.
Correct, I agree, and will change this.
The spec permits aarch32 / armv7 register access via CP14 - but I assume this is omitted deliberately & not intended to be supported at this time.
Yes, because the ETMv4 driver doesn't support arm32 bit at all. We could definitely add this in the future. I will add it to the commit description.
Right now all the CoreSight components are accessed via memory map. Also, we have some common routines in coresight generic code driver (e.g, CS_LOCK, claim/disclaim), which assume the mmio. In order to preserve the generic algorithms at a single place and to allow dynamic switch for ETMs, this series introduces an abstraction layer for accessing a coresight device. It is designed such that the mmio access are fast tracked (i.e, without an indirect function call).
This will also help us to get rid of the driver+attribute specific sysfs show/store routines and replace them with a single routine to access a given register offset (which can be embedded in the dev_ext_attribute). This is not currently implemented in the series, but can be achieved.
Further we switch the generic routines to work with the abstraction. With this in place, we refactor the etm4x code a bit to allow for supporting the system instructions with very little new code. The changes also switch to using the system instructions by default even when we may have an MMIO.
We use TRCDEVARCH for the detection of the ETM component, which is a standard register as per CoreSight architecture, rather than the etm specific id register TRCIDR3. This is for making sure that we are able to detect the ETM via system instructions accurately, when the the trace unit could be anything (etm or a custom trace unit).
I'm assuming you mean TRCIDR1 here -- which in part, defines the etm architecture version. TRCIDR3 does something else entirely.
Yes, definitely, it is a mistake on my side, generated from staring at both of them TRCIDR1 and TRCIDR3 (for the masks).
Not sure I agree with this though - the driver is designed to match the ETM spec so there is no problem with using TRCIDR1 to spot functional variants according to ETM version,
Correct. But for a system instruction based trace unit, we can't trust just the bindings and must use a CoreSight architected register to do the basic detection. Also, I am planning to add support the Future Architectures for the processor trace [0] with the ETM driver, which mandates the use of TRCDEVARCH for the trace version. So, this is more of
Agreed - sysreg must do its own validation of the connected component.
The etm4_init_arch_data() function is not about detecting the presence of an ETMv4 component, but about exploring the capabilities it has. We check 4 bits of the version as a sanity check, but at this point we should be pretty sure we are dealing with an ETM of some kind.
TRCDEVARCH is already used for detection in the AMBA matching code - assuming the table includes the optional CoreSIght UCI. I would imagine that similar detection needs to go on for instruction access - but once we have detected an ETM, then ETM architected registers are sufficient. If the device is not an ETM then it should be detected and rejected early - and the bindings examined to determine why this driver was attached!
I agree with the fact that we should check the device for a supported type at the earliest and must not trust the bindings. With the AMBA based devices we have the early check as mentioned above via the PIDs and the UCI (where available). But where the UCI is not listed, these will be caught by the additional checks on the TRCIDR1 fields. e.g, CTI could have the same PID as an ETM4 and without the UCI field, the driver could assume that an ETM is CTI if the firmware was incorrect
The TRCDEVARCH register was introduced as part of CoreSight Architecture 2.0, the UCI concept as part of CoreSight Architecture 3.0. When we added the UCI checks to the AMBA matching path, this was for newer components that we knew were following the Coresight 3.0 concept of having the same part number for components in the same common function - i.e. ETM, CTI, PMU, with a given CPU.
There was no way of knowing if 100% of the older components that matched the driver using only part number would also pass the UCI check, so this was not added for them (and certainly early CTIs never had a TRCDEVARCH). We did not want to break compatibility, given that some of those components may not be ARM designed. I am not sure what has changed such that we are now prepared to risk making the driver incompatible with older devices.
The act of adding in a check against TRCDEVARCH as part of the etm4_init_arch_data() function adds new and hidden checks to AMBA devices where it was sufficient to have an entry in the probe match table before. Most recent additions include the UCI matching, but older ones don't. I am concerned that this changes may trip up older existing implementations which for some reason may not have TRCDEVCARCH, or have set it to not present.
For the records, ETMv4.0 revision A, says, the PRESENT bit is always Read As One (RAO). So, if they don't implement it or have set to 0, that means that they are broken. But, we could gracefully handle it if the PRESENT bit is 0 and fold back to TRCIDR1.
For this reason, I beleive that the TRCDEVARCH check for the sys reg access should occur on the sysreg specific probe - balancing what happens on the AMBA side. That way the common code remains common.
To make the current situation clear, for those who have not looked at the series, here is the summary :
AMBA driver checks the PIDs to match a device to known ETMv4. Note that CTIs could share the same PIDs and thus we added additional check on the UCI (which is TRCDEVARCH) field for some of the ETMs.
The ETM4 driver assumes that the component is ETMv4 and calls etmv4_init_arch_data() and probes the ETM4 for features, filling in drvdata, including the TRCIDR1. Please note that, at this point there is no guarantee that the unit is indeed ETMv4, if the UCI check (TRCDEVARCH) has not been performed. So, we are possibly treading into wild land here (at least on bring up).
The etm4_probe() confirms that the ETM4 architecture is supported by checking the TRCIDR1 fields (stored in drvdata->arch from step (2)). This check is important (at least for bring up), because if the UCI check is not added for the component, a CTI could be mistaken for an ETM with AMBA devices.
Fact : TRCDEVARCH must be implemented and represent that the component is ETMv4 (this is the basis of UCI check) since ETMv4.0 specification.
Agreed - but unfortunately in the real world not every component correctly follows the spec - hence my concern about tightening up checks on existing devices.
For the system instructions based devices, we have :
Device tree compatible to advertise the presence of a trace unit on a CPU. (no PID checks, this is good, because you don't have to add an entry for a new CPU to be supported upstream, as long as it is compliant with the ETMv4).
To confirm that the CPU tracing unit is ETMv4 compatible, we need to use CoreSight architected register, TRCDEVARCH (the same as UCI). This is because TRCIDR1 may not be what is expected if the Trace unit is not ETMv4, since the encoding is ETM specific. And this must be performed on the host CPU (just like etm4_init_arch_data).
With this series:
AMBA devices pass through the PID check as usual. But the sysreg devices jumps straight to etm4_init_arch_data() via common etm4_probe.
etm4_init_arch_data() will verify that the component is ETMv4 by verifying the TRCDEVARCH for all ETMs (both AMBA and system instructions), before poking the features. This will avoid having to do another round of smp_func_call() in etm4 sysreg probe code.
OK - so using the existing function avoids having two smp_func_call() instances - at the cost of increased complexity in the overall code. If you think this is worth it then fair enough.
- Note: As per Mike's suggestion, this can be further relaxed to check TRCIDR1 for AMBA devices, iff TRCDEVARCH is marked absent for supporting any wild broken implementations out there (I prefer to add a pr_warn_once() for such cases, so that we know such units).
Further the setup of the CSA for the device can happen immediately in the common etm_probe() function, based on *base being NULL or not,
For now, yes. But with the additional changes for supporting [0], this may not. As we need to really see if we have an ETMv4.x or a future unit which has slightly different register list.
Not sure I understand here - are you saying that there may be a case where sysreg access could have a base memory address as well? After ETM4.4 the two have to be mutually exclusive, and even where they are not, there is no way the driver should be using both memory and system register access. The case in [0] may indicate an extension to the programming model, e.g. we currently check if the ETM version is >= 4.3 as this will affect the interpretation of resource selector numbers, and future trace devices may well have more programming model alterations - but this should not affect the access model.
Regards
Mike
rather than as a side effect of the etm4_init_arch_data() call.
[0] https://developer.arm.com/docs/ddi0601/latest , See TRCIDR1
Kind regards Suzuki
-- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK