UPSTREAM: coresight: Introduce device access abstraction
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. Bug: 174685394 Link: https://lore.kernel.org/r/20210110224850.1880240-4-suzuki.poulose@arm.com Cc: Mike Leach <mike.leach@linaro.org> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Link: https://lore.kernel.org/r/20210201181351.1475223-6-mathieu.poirier@linaro.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> (cherry picked from commit 6e736c60a9fe905b3e4f4b07171a31ad602d56d2) Signed-off-by: Qais Yousef <qais.yousef@arm.com> Change-Id: Ie1e48d480cb73155797f7c335db603078ac32fdf
This commit is contained in:

committed by
Todd Kjos

parent
c7a868d7a7
commit
a74e3236dd
@@ -551,6 +551,7 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id)
|
|||||||
dev->platform_data = pdata;
|
dev->platform_data = pdata;
|
||||||
|
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
|
catu_desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
catu_desc.pdata = pdata;
|
catu_desc.pdata = pdata;
|
||||||
catu_desc.dev = dev;
|
catu_desc.dev = dev;
|
||||||
catu_desc.groups = catu_groups;
|
catu_desc.groups = catu_groups;
|
||||||
|
@@ -1452,6 +1452,48 @@ int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(coresight_timeout);
|
EXPORT_SYMBOL_GPL(coresight_timeout);
|
||||||
|
|
||||||
|
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
|
* coresight_release_platform_data: Release references to the devices connected
|
||||||
* to the output port of this device.
|
* to the output port of this device.
|
||||||
@@ -1516,6 +1558,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
|
|||||||
csdev->type = desc->type;
|
csdev->type = desc->type;
|
||||||
csdev->subtype = desc->subtype;
|
csdev->subtype = desc->subtype;
|
||||||
csdev->ops = desc->ops;
|
csdev->ops = desc->ops;
|
||||||
|
csdev->access = desc->access;
|
||||||
csdev->orphan = false;
|
csdev->orphan = false;
|
||||||
|
|
||||||
csdev->dev.type = &coresight_dev_type[desc->type];
|
csdev->dev.type = &coresight_dev_type[desc->type];
|
||||||
|
@@ -868,6 +868,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
|
|||||||
return PTR_ERR(base);
|
return PTR_ERR(base);
|
||||||
|
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
|
cti_desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
|
|
||||||
dev_set_drvdata(dev, drvdata);
|
dev_set_drvdata(dev, drvdata);
|
||||||
|
|
||||||
|
@@ -757,6 +757,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
|
|||||||
return PTR_ERR(base);
|
return PTR_ERR(base);
|
||||||
|
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
|
|
||||||
spin_lock_init(&drvdata->spinlock);
|
spin_lock_init(&drvdata->spinlock);
|
||||||
|
|
||||||
|
@@ -839,6 +839,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
|
|||||||
return PTR_ERR(base);
|
return PTR_ERR(base);
|
||||||
|
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
|
|
||||||
spin_lock_init(&drvdata->spinlock);
|
spin_lock_init(&drvdata->spinlock);
|
||||||
|
|
||||||
|
@@ -1621,6 +1621,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
|
|||||||
return PTR_ERR(base);
|
return PTR_ERR(base);
|
||||||
|
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
|
|
||||||
spin_lock_init(&drvdata->spinlock);
|
spin_lock_init(&drvdata->spinlock);
|
||||||
|
|
||||||
|
@@ -242,6 +242,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
|
|||||||
}
|
}
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
desc.groups = coresight_funnel_groups;
|
desc.groups = coresight_funnel_groups;
|
||||||
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_set_drvdata(dev, drvdata);
|
dev_set_drvdata(dev, drvdata);
|
||||||
|
@@ -254,6 +254,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
|
|||||||
}
|
}
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
desc.groups = replicator_groups;
|
desc.groups = replicator_groups;
|
||||||
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwnode_property_present(dev_fwnode(dev),
|
if (fwnode_property_present(dev_fwnode(dev),
|
||||||
|
@@ -884,6 +884,7 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
|
|||||||
if (IS_ERR(base))
|
if (IS_ERR(base))
|
||||||
return PTR_ERR(base);
|
return PTR_ERR(base);
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
|
|
||||||
ret = stm_get_stimulus_area(dev, &ch_res);
|
ret = stm_get_stimulus_area(dev, &ch_res);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@@ -456,6 +456,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
|
|
||||||
spin_lock_init(&drvdata->spinlock);
|
spin_lock_init(&drvdata->spinlock);
|
||||||
|
|
||||||
|
@@ -149,6 +149,7 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
|
|||||||
return PTR_ERR(base);
|
return PTR_ERR(base);
|
||||||
|
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
|
|
||||||
/* Disable tpiu to support older devices */
|
/* Disable tpiu to support older devices */
|
||||||
tpiu_disable_hw(drvdata);
|
tpiu_disable_hw(drvdata);
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#define _LINUX_CORESIGHT_H
|
#define _LINUX_CORESIGHT_H
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/io.h>
|
||||||
#include <linux/perf_event.h>
|
#include <linux/perf_event.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
|
||||||
@@ -114,6 +115,32 @@ struct coresight_platform_data {
|
|||||||
struct coresight_connection *conns;
|
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)(u32 offset, bool relaxed, bool _64bit);
|
||||||
|
void (*write)(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
|
* struct coresight_desc - description of a component required from drivers
|
||||||
* @type: as defined by @coresight_dev_type.
|
* @type: as defined by @coresight_dev_type.
|
||||||
@@ -125,6 +152,7 @@ struct coresight_platform_data {
|
|||||||
* @groups: operations specific to this component. These will end up
|
* @groups: operations specific to this component. These will end up
|
||||||
* in the component's sysfs sub-directory.
|
* in the component's sysfs sub-directory.
|
||||||
* @name: name for the coresight device, also shown under sysfs.
|
* @name: name for the coresight device, also shown under sysfs.
|
||||||
|
* @access: Describe access to the device
|
||||||
*/
|
*/
|
||||||
struct coresight_desc {
|
struct coresight_desc {
|
||||||
enum coresight_dev_type type;
|
enum coresight_dev_type type;
|
||||||
@@ -134,6 +162,7 @@ struct coresight_desc {
|
|||||||
struct device *dev;
|
struct device *dev;
|
||||||
const struct attribute_group **groups;
|
const struct attribute_group **groups;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
struct csdev_access access;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -173,7 +202,8 @@ struct coresight_sysfs_link {
|
|||||||
* @type: as defined by @coresight_dev_type.
|
* @type: as defined by @coresight_dev_type.
|
||||||
* @subtype: as defined by @coresight_dev_subtype.
|
* @subtype: as defined by @coresight_dev_subtype.
|
||||||
* @ops: generic operations for this component, as defined
|
* @ops: generic operations for this component, as defined
|
||||||
by @coresight_ops.
|
* by @coresight_ops.
|
||||||
|
* @access: Device i/o access abstraction for this device.
|
||||||
* @dev: The device entity associated to this component.
|
* @dev: The device entity associated to this component.
|
||||||
* @refcnt: keep track of what is in use.
|
* @refcnt: keep track of what is in use.
|
||||||
* @orphan: true if the component has connections that haven't been linked.
|
* @orphan: true if the component has connections that haven't been linked.
|
||||||
@@ -195,6 +225,7 @@ struct coresight_device {
|
|||||||
enum coresight_dev_type type;
|
enum coresight_dev_type type;
|
||||||
union coresight_dev_subtype subtype;
|
union coresight_dev_subtype subtype;
|
||||||
const struct coresight_ops *ops;
|
const struct coresight_ops *ops;
|
||||||
|
struct csdev_access access;
|
||||||
struct device dev;
|
struct device dev;
|
||||||
atomic_t *refcnt;
|
atomic_t *refcnt;
|
||||||
bool orphan;
|
bool orphan;
|
||||||
@@ -326,6 +357,104 @@ struct coresight_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_CORESIGHT)
|
#if IS_ENABLED(CONFIG_CORESIGHT)
|
||||||
|
|
||||||
|
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(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(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(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(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(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(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(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(val, offset, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !CONFIG_64BIT */
|
||||||
|
|
||||||
|
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 /* CONFIG_64BIT */
|
||||||
|
|
||||||
extern struct coresight_device *
|
extern struct coresight_device *
|
||||||
coresight_register(struct coresight_desc *desc);
|
coresight_register(struct coresight_desc *desc);
|
||||||
extern void coresight_unregister(struct coresight_device *csdev);
|
extern void coresight_unregister(struct coresight_device *csdev);
|
||||||
@@ -343,6 +472,18 @@ extern char *coresight_alloc_device_name(struct coresight_dev_list *devs,
|
|||||||
struct device *dev);
|
struct device *dev);
|
||||||
|
|
||||||
extern bool coresight_loses_context_with_cpu(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
|
#else
|
||||||
static inline struct coresight_device *
|
static inline struct coresight_device *
|
||||||
coresight_register(struct coresight_desc *desc) { return NULL; }
|
coresight_register(struct coresight_desc *desc) { return NULL; }
|
||||||
@@ -369,10 +510,54 @@ static inline bool coresight_loses_context_with_cpu(struct device *dev)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
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 /* IS_ENABLED(CONFIG_CORESIGHT) */
|
||||||
|
|
||||||
extern int coresight_get_cpu(struct device *dev);
|
extern int coresight_get_cpu(struct device *dev);
|
||||||
|
|
||||||
struct coresight_platform_data *coresight_get_platform_data(struct device *dev);
|
struct coresight_platform_data *coresight_get_platform_data(struct device *dev);
|
||||||
|
|
||||||
#endif
|
#endif /* _LINUX_COREISGHT_H */
|
||||||
|
Reference in New Issue
Block a user