Commit 6e736c60 authored by Suzuki K Poulose's avatar Suzuki K Poulose Committed by Greg Kroah-Hartman

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.

Link: https://lore.kernel.org/r/20210110224850.1880240-4-suzuki.poulose@arm.com
Cc: Mike Leach <mike.leach@linaro.org>
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Link: https://lore.kernel.org/r/20210201181351.1475223-6-mathieu.poirier@linaro.orgSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent df81b438
...@@ -551,6 +551,7 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -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;
......
...@@ -1458,6 +1458,48 @@ int coresight_timeout(void __iomem *addr, u32 offset, int position, int value) ...@@ -1458,6 +1458,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.
...@@ -1522,6 +1564,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) ...@@ -1522,6 +1564,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];
......
...@@ -870,6 +870,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -870,6 +870,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) ...@@ -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) ...@@ -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);
......
...@@ -1626,6 +1626,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -1626,6 +1626,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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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, ...@@ -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) ...@@ -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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment