mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
coresight: Updates for Linux v7.1
CoreSight self hosted tracing subsystem updates for Linux v7.1, includes:
- Fix unregistration related issues
- Clean up CTI power management and sysfs code
- Miscellaneous fixes
- MAINTAINERS: Add Leo Yan as Reviewer
- MAINTAINERS: Update Mike's email address
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEuFy0byloRoXZHaWBxcXRZPKyBqEFAmnWh6cACgkQxcXRZPKy
BqF55hAAmnd6RQRNhbTukjORsP/LENV5F7OWZuEI4y8OxbwBkTPA3gnZCNNEURqQ
J2pymcabYzxZJ6wwXFOYpJH1ZM78cIhW6u0LugXb844c85k4G/K7t44ENYz0VKuL
aBF4rzRfng4TprLIZQvYq/ND/tP4MGJ/3Il+IVcrCF+XSFj056N7VlrI5vKCjNgM
JzfHCYNi4NiqXUzdECbzTjdEejg1eAe8xeIuNb7FSvfJ21a8iy2toGYtHmaecnNg
Eir4CB1ZclQlyrQLEEjH22sTnjxBJRPXtkvTpUDTuIipGzzEZHdN7a9cWH5sNFxh
VWCqI3PXs6/S6FBaCzjY3rL7qcAPCblPO5CkXajMlvj7+d7TDJL4jtB7BitNe1rY
x/OR3J8fmsJMhxKKAlYnKPMMXlum50DzhPJvl4JUXd5EJnTLIkG6Z6vajCQm2diR
WpI/ADee4mk3k9fhEfkiM7mXfKfmvId4/2W3p2dKDk3w8yl0htcuSIo6M3HgIi7w
Ffedjh2+NM7f/8Gwn5AqORV1besCmCyIVs8alCHC9oegUSm/Kzxcf4K34THIeMub
aejRbUU0QJtH2tVUPg6OD5owIwEJ5dZrGVKr5jtTP6s9W1G0MNX3EWsKvMixDjUw
Tc6cM3jcGvmeqBOGlEVbBKmn17WPcnNa1bQZ6RfYyx6mtYf3b5A=
=6zJ9
-----END PGP SIGNATURE-----
Merge tag 'coresight-next-v7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux into char-misc-next
Suzuki writes:
coresight: Updates for Linux v7.1
CoreSight self hosted tracing subsystem updates for Linux v7.1, includes:
- Fix unregistration related issues
- Clean up CTI power management and sysfs code
- Miscellaneous fixes
- MAINTAINERS: Add Leo Yan as Reviewer
- MAINTAINERS: Update Mike's email address
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
* tag 'coresight-next-v7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/coresight/linux: (25 commits)
coresight: tpdm: fix invalid MMIO access issue
coresight: tpdm: add traceid_show for checking traceid
coresight: platform: check the availability of the endpoint before parse
coresight: cti: fix the check condition in inout_sel_store
MAINTAINERS: coresight: Add Leo Yan as Reviewer
coresight: cti: Properly handle negative offsets in cti_reg32_{show|store}()
coresight: cti: Remove hw_enabled flag
coresight: cti: Remove hw_powered flag
coresight: cti: Rename cti_active() to cti_is_active()
coresight: cti: Remove CPU power management code
coresight: cti: Access ASICCTL only when implemented
coresight: cti: Fix register reads
coresight: cti: Make spinlock usage consistent
drivers/hwtracing/coresight: remove unneeded variable in tmc_crashdata_release()
MAINTAINERS: Change e-mail address for reviewer
coresight: ctcu: fix the spin_bug
coresight: Unify bus unregistration via coresight_unregister()
coresight: Do not mix success path with failure handling
coresight: Move sink validation into etm_perf_add_symlink_sink()
coresight: Refactor sysfs connection group cleanup
...
This commit is contained in:
commit
1c0220a615
1
.mailmap
1
.mailmap
|
|
@ -576,6 +576,7 @@ Michel Lespinasse <michel@lespinasse.org> <walken@google.com>
|
|||
Michel Lespinasse <michel@lespinasse.org> <walken@zoy.org>
|
||||
Mickaël Salaün <mic@digikod.net> <mic@linux.microsoft.com>
|
||||
Miguel Ojeda <ojeda@kernel.org> <miguel.ojeda.sandonis@gmail.com>
|
||||
Mike Leach <mike.leach@arm.com> <mike.leach@linaro.org>
|
||||
Mike Rapoport <rppt@kernel.org> <mike@compulab.co.il>
|
||||
Mike Rapoport <rppt@kernel.org> <mike.rapoport@gmail.com>
|
||||
Mike Rapoport <rppt@kernel.org> <rppt@linux.ibm.com>
|
||||
|
|
|
|||
|
|
@ -278,3 +278,13 @@ Date: Aug 2025
|
|||
KernelVersion 6.18
|
||||
Contact: Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
Description: (Read) Show hardware context information of device.
|
||||
|
||||
What: /sys/bus/coresight/devices/<tpdm-name>/traceid
|
||||
Date: March 2026
|
||||
KernelVersion: 7.1
|
||||
Contact: Jie Gan <jie.gan@oss.qualcomm.com>
|
||||
Description:
|
||||
(R) Show the trace ID that will appear in the trace stream
|
||||
coming from this TPDM. The trace ID is inherited from the
|
||||
connected TPDA device and is fixed for the lifetime of the
|
||||
device. Returns -EINVAL if the device has not been enabled yet.
|
||||
|
|
|
|||
|
|
@ -2725,8 +2725,9 @@ N: digicolor
|
|||
|
||||
ARM/CORESIGHT FRAMEWORK AND DRIVERS
|
||||
M: Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
R: Mike Leach <mike.leach@linaro.org>
|
||||
R: Mike Leach <mike.leach@arm.com>
|
||||
R: James Clark <james.clark@linaro.org>
|
||||
R: Leo Yan <leo.yan@arm.com>
|
||||
L: coresight@lists.linaro.org (moderated for non-subscribers)
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
|
|
@ -20734,7 +20735,7 @@ PERFORMANCE EVENTS TOOLING ARM64
|
|||
R: John Garry <john.g.garry@oracle.com>
|
||||
R: Will Deacon <will@kernel.org>
|
||||
R: James Clark <james.clark@linaro.org>
|
||||
R: Mike Leach <mike.leach@linaro.org>
|
||||
R: Mike Leach <mike.leach@arm.com>
|
||||
R: Leo Yan <leo.yan@linux.dev>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@
|
|||
#define catu_dbg(x, ...) do {} while (0)
|
||||
#endif
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(catu_devs, "catu");
|
||||
|
||||
struct catu_etr_buf {
|
||||
struct tmc_sg_table *catu_table;
|
||||
dma_addr_t sladdr;
|
||||
|
|
@ -530,7 +528,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
catu_desc.name = coresight_alloc_device_name(&catu_devs, dev);
|
||||
catu_desc.name = coresight_alloc_device_name("catu", dev);
|
||||
if (!catu_desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ struct coresight_node {
|
|||
const u32 coresight_barrier_pkt[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
|
||||
EXPORT_SYMBOL_GPL(coresight_barrier_pkt);
|
||||
|
||||
/* List maintains the device index */
|
||||
static LIST_HEAD(coresight_dev_idx_list);
|
||||
|
||||
static const struct cti_assoc_op *cti_assoc_ops;
|
||||
|
||||
void coresight_set_cti_ops(const struct cti_assoc_op *cti_op)
|
||||
|
|
@ -1149,7 +1152,6 @@ static int coresight_clear_filter_source(struct device *dev, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* coresight_remove_conns - Remove other device's references to this device */
|
||||
static void coresight_remove_conns(struct coresight_device *csdev)
|
||||
{
|
||||
int i, j;
|
||||
|
|
@ -1159,10 +1161,6 @@ static void coresight_remove_conns(struct coresight_device *csdev)
|
|||
bus_for_each_dev(&coresight_bustype, NULL, csdev,
|
||||
coresight_clear_filter_source);
|
||||
|
||||
/*
|
||||
* Remove the input connection references from the destination device
|
||||
* for each output connection.
|
||||
*/
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
|
||||
conn = csdev->pdata->out_conns[i];
|
||||
if (conn->filter_src_fwnode) {
|
||||
|
|
@ -1173,6 +1171,13 @@ static void coresight_remove_conns(struct coresight_device *csdev)
|
|||
if (!conn->dest_dev)
|
||||
continue;
|
||||
|
||||
/* Remove sysfs links for the output connection */
|
||||
coresight_remove_links(csdev, conn);
|
||||
|
||||
/*
|
||||
* Remove the input connection references from the destination
|
||||
* device for each output connection.
|
||||
*/
|
||||
for (j = 0; j < conn->dest_dev->pdata->nr_inconns; ++j)
|
||||
if (conn->dest_dev->pdata->in_conns[j] == conn) {
|
||||
conn->dest_dev->pdata->in_conns[j] = NULL;
|
||||
|
|
@ -1195,6 +1200,8 @@ static void coresight_remove_conns(struct coresight_device *csdev)
|
|||
coresight_remove_links(conn->src_dev, conn);
|
||||
conn->dest_dev = NULL;
|
||||
}
|
||||
|
||||
coresight_remove_conns_sysfs_group(csdev);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1295,17 +1302,13 @@ void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset)
|
|||
* coresight_release_platform_data: Release references to the devices connected
|
||||
* to the output port of this device.
|
||||
*/
|
||||
void coresight_release_platform_data(struct coresight_device *csdev,
|
||||
struct device *dev,
|
||||
void coresight_release_platform_data(struct device *dev,
|
||||
struct coresight_platform_data *pdata)
|
||||
{
|
||||
int i;
|
||||
struct coresight_connection **conns = pdata->out_conns;
|
||||
|
||||
for (i = 0; i < pdata->nr_outconns; i++) {
|
||||
/* If we have made the links, remove them now */
|
||||
if (csdev && conns[i]->dest_dev)
|
||||
coresight_remove_links(csdev, conns[i]);
|
||||
/*
|
||||
* Drop the refcount and clear the handle as this device
|
||||
* is going away
|
||||
|
|
@ -1317,8 +1320,6 @@ void coresight_release_platform_data(struct coresight_device *csdev,
|
|||
devm_kfree(dev, pdata->out_conns);
|
||||
devm_kfree(dev, pdata->in_conns);
|
||||
devm_kfree(dev, pdata);
|
||||
if (csdev)
|
||||
coresight_remove_conns_sysfs_group(csdev);
|
||||
}
|
||||
|
||||
struct coresight_device *coresight_register(struct coresight_desc *desc)
|
||||
|
|
@ -1346,12 +1347,6 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
|
|||
csdev->dev.parent = desc->dev;
|
||||
csdev->dev.release = coresight_device_release;
|
||||
csdev->dev.bus = &coresight_bustype;
|
||||
/*
|
||||
* Hold the reference to our parent device. This will be
|
||||
* dropped only in coresight_device_release().
|
||||
*/
|
||||
csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
|
||||
dev_set_name(&csdev->dev, "%s", desc->name);
|
||||
|
||||
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
|
||||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
|
||||
|
|
@ -1363,6 +1358,14 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
|
|||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Hold the reference to our parent device. This will be
|
||||
* dropped only in coresight_device_release().
|
||||
*/
|
||||
csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
|
||||
dev_set_name(&csdev->dev, "%s", desc->name);
|
||||
|
||||
/*
|
||||
* Make sure the device registration and the connection fixup
|
||||
* are synchronised, so that we don't see uninitialised devices
|
||||
|
|
@ -1380,37 +1383,30 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
|
||||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
|
||||
sink_ops(csdev)->alloc_buffer) {
|
||||
ret = etm_perf_add_symlink_sink(csdev);
|
||||
|
||||
if (ret) {
|
||||
device_unregister(&csdev->dev);
|
||||
/*
|
||||
* As with the above, all resources are free'd
|
||||
* explicitly via coresight_device_release() triggered
|
||||
* from put_device(), which is in turn called from
|
||||
* function device_unregister().
|
||||
*/
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
/* Device is now registered */
|
||||
registered = true;
|
||||
|
||||
ret = etm_perf_add_symlink_sink(csdev);
|
||||
if (ret && ret != -EOPNOTSUPP)
|
||||
goto out_unlock;
|
||||
|
||||
ret = coresight_create_conns_sysfs_group(csdev);
|
||||
if (!ret)
|
||||
ret = coresight_fixup_orphan_conns(csdev);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
ret = coresight_fixup_orphan_conns(csdev);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
mutex_unlock(&coresight_mutex);
|
||||
|
||||
if (cti_assoc_ops && cti_assoc_ops->add)
|
||||
cti_assoc_ops->add(csdev);
|
||||
|
||||
return csdev;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&coresight_mutex);
|
||||
/* Success */
|
||||
if (!ret) {
|
||||
if (cti_assoc_ops && cti_assoc_ops->add)
|
||||
cti_assoc_ops->add(csdev);
|
||||
return csdev;
|
||||
}
|
||||
|
||||
/* Unregister the device if needed */
|
||||
if (registered) {
|
||||
|
|
@ -1419,41 +1415,76 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
|
|||
}
|
||||
|
||||
err_out:
|
||||
/* Cleanup the connection information */
|
||||
coresight_release_platform_data(NULL, desc->dev, desc->pdata);
|
||||
coresight_release_platform_data(desc->dev, desc->pdata);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_register);
|
||||
|
||||
void coresight_unregister(struct coresight_device *csdev)
|
||||
{
|
||||
etm_perf_del_symlink_sink(csdev);
|
||||
/* Remove references of that device in the topology */
|
||||
if (cti_assoc_ops && cti_assoc_ops->remove)
|
||||
cti_assoc_ops->remove(csdev);
|
||||
|
||||
mutex_lock(&coresight_mutex);
|
||||
etm_perf_del_symlink_sink(csdev);
|
||||
coresight_remove_conns(csdev);
|
||||
coresight_clear_default_sink(csdev);
|
||||
coresight_release_platform_data(csdev, csdev->dev.parent, csdev->pdata);
|
||||
coresight_release_platform_data(csdev->dev.parent, csdev->pdata);
|
||||
device_unregister(&csdev->dev);
|
||||
mutex_unlock(&coresight_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_unregister);
|
||||
|
||||
|
||||
/*
|
||||
* coresight_search_device_idx - Search the fwnode handle of a device
|
||||
* in the given dev_idx list. Must be called with the coresight_mutex held.
|
||||
*
|
||||
* Returns the index of the entry, when found. Otherwise, -ENOENT.
|
||||
*/
|
||||
static int coresight_search_device_idx(struct coresight_dev_list *dict,
|
||||
struct fwnode_handle *fwnode)
|
||||
static struct coresight_dev_list *
|
||||
coresight_allocate_device_list(const char *prefix)
|
||||
{
|
||||
int i;
|
||||
struct coresight_dev_list *list;
|
||||
|
||||
for (i = 0; i < dict->nr_idx; i++)
|
||||
if (dict->fwnode_list[i] == fwnode)
|
||||
return i;
|
||||
return -ENOENT;
|
||||
/* Check if have already allocated */
|
||||
list_for_each_entry(list, &coresight_dev_idx_list, node) {
|
||||
if (!strcmp(list->pfx, prefix))
|
||||
return list;
|
||||
}
|
||||
|
||||
list = kzalloc(sizeof(*list), GFP_KERNEL);
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
list->pfx = kstrdup(prefix, GFP_KERNEL);
|
||||
if (!list->pfx) {
|
||||
kfree(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_add(&list->node, &coresight_dev_idx_list);
|
||||
return list;
|
||||
}
|
||||
|
||||
static int coresight_allocate_device_idx(struct coresight_dev_list *list,
|
||||
struct device *dev)
|
||||
{
|
||||
struct fwnode_handle **fwnode_list;
|
||||
struct fwnode_handle *fwnode = dev_fwnode(dev);
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < list->nr_idx; idx++)
|
||||
if (list->fwnode_list[idx] == fwnode)
|
||||
return idx;
|
||||
|
||||
/* Make space for the new entry */
|
||||
idx = list->nr_idx;
|
||||
fwnode_list = krealloc_array(list->fwnode_list,
|
||||
idx + 1, sizeof(*list->fwnode_list),
|
||||
GFP_KERNEL);
|
||||
if (!fwnode_list)
|
||||
return -ENOMEM;
|
||||
|
||||
fwnode_list[idx] = fwnode;
|
||||
list->fwnode_list = fwnode_list;
|
||||
list->nr_idx = idx + 1;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static bool coresight_compare_type(enum coresight_dev_type type_a,
|
||||
|
|
@ -1527,45 +1558,63 @@ bool coresight_loses_context_with_cpu(struct device *dev)
|
|||
EXPORT_SYMBOL_GPL(coresight_loses_context_with_cpu);
|
||||
|
||||
/*
|
||||
* coresight_alloc_device_name - Get an index for a given device in the
|
||||
* device index list specific to a driver. An index is allocated for a
|
||||
* device and is tracked with the fwnode_handle to prevent allocating
|
||||
* coresight_alloc_device_name - Get an index for a given device in the list
|
||||
* specific to a driver (presented by the prefix string). An index is allocated
|
||||
* for a device and is tracked with the fwnode_handle to prevent allocating
|
||||
* duplicate indices for the same device (e.g, if we defer probing of
|
||||
* a device due to dependencies), in case the index is requested again.
|
||||
*/
|
||||
char *coresight_alloc_device_name(struct coresight_dev_list *dict,
|
||||
struct device *dev)
|
||||
char *coresight_alloc_device_name(const char *prefix, struct device *dev)
|
||||
{
|
||||
int idx;
|
||||
struct coresight_dev_list *list;
|
||||
char *name = NULL;
|
||||
struct fwnode_handle **list;
|
||||
int idx;
|
||||
|
||||
mutex_lock(&coresight_mutex);
|
||||
|
||||
idx = coresight_search_device_idx(dict, dev_fwnode(dev));
|
||||
if (idx < 0) {
|
||||
/* Make space for the new entry */
|
||||
idx = dict->nr_idx;
|
||||
list = krealloc_array(dict->fwnode_list,
|
||||
idx + 1, sizeof(*dict->fwnode_list),
|
||||
GFP_KERNEL);
|
||||
if (ZERO_OR_NULL_PTR(list)) {
|
||||
idx = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
list = coresight_allocate_device_list(prefix);
|
||||
if (!list)
|
||||
goto done;
|
||||
|
||||
list[idx] = dev_fwnode(dev);
|
||||
dict->fwnode_list = list;
|
||||
dict->nr_idx = idx + 1;
|
||||
}
|
||||
idx = coresight_allocate_device_idx(list, dev);
|
||||
|
||||
name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", dict->pfx, idx);
|
||||
/*
|
||||
* If index allocation fails, the device list is not released here;
|
||||
* it is instead freed later by coresight_release_device_list() when
|
||||
* the coresight_core module is unloaded.
|
||||
*/
|
||||
if (idx < 0)
|
||||
goto done;
|
||||
|
||||
name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", list->pfx, idx);
|
||||
done:
|
||||
mutex_unlock(&coresight_mutex);
|
||||
return name;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_alloc_device_name);
|
||||
|
||||
static void coresight_release_device_list(void)
|
||||
{
|
||||
struct coresight_dev_list *list, *next;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Here is no need to take coresight_mutex; this is during core module
|
||||
* unloading, no race condition with other modules.
|
||||
*/
|
||||
|
||||
list_for_each_entry_safe(list, next, &coresight_dev_idx_list, node) {
|
||||
for (i = 0; i < list->nr_idx; i++)
|
||||
list->fwnode_list[i] = NULL;
|
||||
list->nr_idx = 0;
|
||||
list_del(&list->node);
|
||||
|
||||
kfree(list->pfx);
|
||||
kfree(list->fwnode_list);
|
||||
kfree(list);
|
||||
}
|
||||
}
|
||||
|
||||
const struct bus_type coresight_bustype = {
|
||||
.name = "coresight",
|
||||
};
|
||||
|
|
@ -1639,6 +1688,7 @@ static void __exit coresight_exit(void)
|
|||
&coresight_notifier);
|
||||
etm_perf_exit();
|
||||
bus_unregister(&coresight_bustype);
|
||||
coresight_release_device_list();
|
||||
}
|
||||
|
||||
module_init(coresight_init);
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@
|
|||
#include "coresight-ctcu.h"
|
||||
#include "coresight-priv.h"
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(ctcu_devs, "ctcu");
|
||||
|
||||
#define ctcu_writel(drvdata, val, offset) __raw_writel((val), drvdata->base + offset)
|
||||
#define ctcu_readl(drvdata, offset) __raw_readl(drvdata->base + offset)
|
||||
|
||||
|
|
@ -187,7 +185,7 @@ static int ctcu_probe(struct platform_device *pdev)
|
|||
void __iomem *base;
|
||||
int i, ret;
|
||||
|
||||
desc.name = coresight_alloc_device_name(&ctcu_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("ctcu", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -228,6 +226,7 @@ static int ctcu_probe(struct platform_device *pdev)
|
|||
desc.dev = dev;
|
||||
desc.ops = &ctcu_ops;
|
||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||
raw_spin_lock_init(&drvdata->spin_lock);
|
||||
|
||||
drvdata->csdev = coresight_register(&desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
|
|
|
|||
|
|
@ -42,21 +42,6 @@ static DEFINE_MUTEX(ect_mutex);
|
|||
#define csdev_to_cti_drvdata(csdev) \
|
||||
dev_get_drvdata(csdev->dev.parent)
|
||||
|
||||
/* power management handling */
|
||||
static int nr_cti_cpu;
|
||||
|
||||
/* quick lookup list for CPU bound CTIs when power handling */
|
||||
static struct cti_drvdata *cti_cpu_drvdata[NR_CPUS];
|
||||
|
||||
/*
|
||||
* CTI naming. CTI bound to cores will have the name cti_cpu<N> where
|
||||
* N is the CPU ID. System CTIs will have the name cti_sys<I> where I
|
||||
* is an index allocated by order of discovery.
|
||||
*
|
||||
* CTI device name list - for CTI not bound to cores.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
|
@ -77,7 +62,8 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
|
|||
|
||||
/* other regs */
|
||||
writel_relaxed(config->ctigate, drvdata->base + CTIGATE);
|
||||
writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
|
||||
if (config->asicctl_impl)
|
||||
writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
|
||||
writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);
|
||||
|
||||
/* re-enable CTI */
|
||||
|
|
@ -90,60 +76,24 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
|
|||
static int cti_enable_hw(struct cti_drvdata *drvdata)
|
||||
{
|
||||
struct cti_config *config = &drvdata->config;
|
||||
unsigned long flags;
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
raw_spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
/* no need to do anything if enabled or unpowered*/
|
||||
if (config->hw_enabled || !config->hw_powered)
|
||||
/* no need to do anything if enabled */
|
||||
if (cti_is_active(config))
|
||||
goto cti_state_unchanged;
|
||||
|
||||
/* claim the device */
|
||||
rc = coresight_claim_device(drvdata->csdev);
|
||||
if (rc)
|
||||
goto cti_err_not_enabled;
|
||||
return rc;
|
||||
|
||||
cti_write_all_hw_regs(drvdata);
|
||||
|
||||
config->hw_enabled = true;
|
||||
drvdata->config.enable_req_count++;
|
||||
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
return rc;
|
||||
|
||||
cti_state_unchanged:
|
||||
drvdata->config.enable_req_count++;
|
||||
|
||||
/* cannot enable due to error */
|
||||
cti_err_not_enabled:
|
||||
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* re-enable CTI on CPU when using CPU hotplug */
|
||||
static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
|
||||
{
|
||||
struct cti_config *config = &drvdata->config;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
config->hw_powered = true;
|
||||
|
||||
/* no need to do anything if no enable request */
|
||||
if (!drvdata->config.enable_req_count)
|
||||
goto cti_hp_not_enabled;
|
||||
|
||||
/* try to claim the device */
|
||||
if (coresight_claim_device(drvdata->csdev))
|
||||
goto cti_hp_not_enabled;
|
||||
|
||||
cti_write_all_hw_regs(drvdata);
|
||||
config->hw_enabled = true;
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return;
|
||||
|
||||
/* did not re-enable due to no claim / no request */
|
||||
cti_hp_not_enabled:
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* disable hardware */
|
||||
|
|
@ -151,39 +101,36 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
|
|||
{
|
||||
struct cti_config *config = &drvdata->config;
|
||||
struct coresight_device *csdev = drvdata->csdev;
|
||||
int ret = 0;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
/* don't allow negative refcounts, return an error */
|
||||
if (!drvdata->config.enable_req_count) {
|
||||
ret = -EINVAL;
|
||||
goto cti_not_disabled;
|
||||
}
|
||||
if (!cti_is_active(config))
|
||||
return -EINVAL;
|
||||
|
||||
/* check refcount - disable on 0 */
|
||||
if (--drvdata->config.enable_req_count > 0)
|
||||
goto cti_not_disabled;
|
||||
|
||||
/* no need to do anything if disabled or cpu unpowered */
|
||||
if (!config->hw_enabled || !config->hw_powered)
|
||||
goto cti_not_disabled;
|
||||
return 0;
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
/* disable CTI */
|
||||
writel_relaxed(0, drvdata->base + CTICONTROL);
|
||||
config->hw_enabled = false;
|
||||
|
||||
coresight_disclaim_device_unlocked(csdev);
|
||||
CS_LOCK(drvdata->base);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not disabled this call */
|
||||
cti_not_disabled:
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return ret;
|
||||
u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset)
|
||||
{
|
||||
int val;
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
val = readl_relaxed(drvdata->base + offset);
|
||||
CS_LOCK(drvdata->base);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value)
|
||||
|
|
@ -198,11 +145,11 @@ void cti_write_intack(struct device *dev, u32 ackval)
|
|||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
struct cti_config *config = &drvdata->config;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
/* write if enabled */
|
||||
if (cti_active(config))
|
||||
if (cti_is_active(config))
|
||||
cti_write_single_reg(drvdata, CTIINTACK, ackval);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -240,6 +187,8 @@ static void cti_set_default_config(struct device *dev,
|
|||
config->trig_filter_enable = true;
|
||||
config->ctigate = GENMASK(config->nr_ctm_channels - 1, 0);
|
||||
config->enable_req_count = 0;
|
||||
|
||||
config->asicctl_impl = !!FIELD_GET(GENMASK(4, 0), devid);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -369,7 +318,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
|
|||
reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
|
||||
CTIOUTEN(trigger_idx));
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
/* read - modify write - the trigger / channel enable value */
|
||||
reg_value = direction == CTI_TRIG_IN ? config->ctiinen[trigger_idx] :
|
||||
|
|
@ -386,9 +335,9 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
|
|||
config->ctiouten[trigger_idx] = reg_value;
|
||||
|
||||
/* write through if enabled */
|
||||
if (cti_active(config))
|
||||
if (cti_is_active(config))
|
||||
cti_write_single_reg(drvdata, reg_offset, reg_value);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -406,7 +355,8 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
|
|||
|
||||
chan_bitmask = BIT(channel_idx);
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
reg_value = config->ctigate;
|
||||
switch (op) {
|
||||
case CTI_GATE_CHAN_ENABLE:
|
||||
|
|
@ -423,10 +373,10 @@ int cti_channel_gate_op(struct device *dev, enum cti_chan_gate_op op,
|
|||
}
|
||||
if (err == 0) {
|
||||
config->ctigate = reg_value;
|
||||
if (cti_active(config))
|
||||
if (cti_is_active(config))
|
||||
cti_write_single_reg(drvdata, CTIGATE, reg_value);
|
||||
}
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -445,7 +395,8 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
|
|||
|
||||
chan_bitmask = BIT(channel_idx);
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
reg_value = config->ctiappset;
|
||||
switch (op) {
|
||||
case CTI_CHAN_SET:
|
||||
|
|
@ -471,9 +422,8 @@ int cti_channel_setop(struct device *dev, enum cti_chan_set_op op,
|
|||
break;
|
||||
}
|
||||
|
||||
if ((err == 0) && cti_active(config))
|
||||
if ((err == 0) && cti_is_active(config))
|
||||
cti_write_single_reg(drvdata, reg_offset, reg_value);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -658,146 +608,6 @@ static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata)
|
|||
}
|
||||
}
|
||||
|
||||
/** cti PM callbacks **/
|
||||
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;
|
||||
|
||||
if (!cti_cpu_drvdata[cpu])
|
||||
return NOTIFY_OK;
|
||||
|
||||
drvdata = cti_cpu_drvdata[cpu];
|
||||
csdev = drvdata->csdev;
|
||||
|
||||
if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))
|
||||
return NOTIFY_BAD;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
|
||||
switch (cmd) {
|
||||
case CPU_PM_ENTER:
|
||||
/* CTI regs all static - we have a copy & nothing to save */
|
||||
drvdata->config.hw_powered = false;
|
||||
if (drvdata->config.hw_enabled)
|
||||
coresight_disclaim_device(csdev);
|
||||
break;
|
||||
|
||||
case CPU_PM_ENTER_FAILED:
|
||||
drvdata->config.hw_powered = true;
|
||||
if (drvdata->config.hw_enabled) {
|
||||
if (coresight_claim_device(csdev))
|
||||
drvdata->config.hw_enabled = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_PM_EXIT:
|
||||
/* write hardware registers to re-enable. */
|
||||
drvdata->config.hw_powered = true;
|
||||
drvdata->config.hw_enabled = false;
|
||||
|
||||
/* check enable reference count to enable HW */
|
||||
if (drvdata->config.enable_req_count) {
|
||||
/* check we can claim the device as we re-power */
|
||||
if (coresight_claim_device(csdev))
|
||||
goto cti_notify_exit;
|
||||
|
||||
drvdata->config.hw_enabled = true;
|
||||
cti_write_all_hw_regs(drvdata);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
notify_res = NOTIFY_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
cti_notify_exit:
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return notify_res;
|
||||
}
|
||||
|
||||
static struct notifier_block cti_cpu_pm_nb = {
|
||||
.notifier_call = cti_cpu_pm_notify,
|
||||
};
|
||||
|
||||
/* CPU HP handlers */
|
||||
static int cti_starting_cpu(unsigned int cpu)
|
||||
{
|
||||
struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu];
|
||||
|
||||
if (!drvdata)
|
||||
return 0;
|
||||
|
||||
cti_cpuhp_enable_hw(drvdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cti_dying_cpu(unsigned int cpu)
|
||||
{
|
||||
struct cti_drvdata *drvdata = cti_cpu_drvdata[cpu];
|
||||
|
||||
if (!drvdata)
|
||||
return 0;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
drvdata->config.hw_powered = false;
|
||||
if (drvdata->config.hw_enabled)
|
||||
coresight_disclaim_device(drvdata->csdev);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cti_pm_setup(struct cti_drvdata *drvdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (drvdata->ctidev.cpu == -1)
|
||||
return 0;
|
||||
|
||||
if (nr_cti_cpu)
|
||||
goto done;
|
||||
|
||||
cpus_read_lock();
|
||||
ret = cpuhp_setup_state_nocalls_cpuslocked(
|
||||
CPUHP_AP_ARM_CORESIGHT_CTI_STARTING,
|
||||
"arm/coresight_cti:starting",
|
||||
cti_starting_cpu, cti_dying_cpu);
|
||||
if (ret) {
|
||||
cpus_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = cpu_pm_register_notifier(&cti_cpu_pm_nb);
|
||||
cpus_read_unlock();
|
||||
if (ret) {
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);
|
||||
return ret;
|
||||
}
|
||||
|
||||
done:
|
||||
nr_cti_cpu++;
|
||||
cti_cpu_drvdata[drvdata->ctidev.cpu] = drvdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* release PM registrations */
|
||||
static void cti_pm_release(struct cti_drvdata *drvdata)
|
||||
{
|
||||
if (drvdata->ctidev.cpu == -1)
|
||||
return;
|
||||
|
||||
cti_cpu_drvdata[drvdata->ctidev.cpu] = NULL;
|
||||
if (--nr_cti_cpu == 0) {
|
||||
cpu_pm_unregister_notifier(&cti_cpu_pm_nb);
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_CTI_STARTING);
|
||||
}
|
||||
}
|
||||
|
||||
/** cti ect operations **/
|
||||
int cti_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
struct coresight_path *path)
|
||||
|
|
@ -823,17 +633,13 @@ static const struct coresight_ops cti_ops = {
|
|||
.helper_ops = &cti_ops_ect,
|
||||
};
|
||||
|
||||
/*
|
||||
* Free up CTI specific resources
|
||||
* called by dev->release, need to call down to underlying csdev release.
|
||||
*/
|
||||
static void cti_device_release(struct device *dev)
|
||||
static void cti_remove(struct amba_device *adev)
|
||||
{
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(&adev->dev);
|
||||
struct cti_drvdata *ect_item, *ect_tmp;
|
||||
|
||||
mutex_lock(&ect_mutex);
|
||||
cti_pm_release(drvdata);
|
||||
cti_remove_conn_xrefs(drvdata);
|
||||
|
||||
/* remove from the list */
|
||||
list_for_each_entry_safe(ect_item, ect_tmp, &ect_net, node) {
|
||||
|
|
@ -844,17 +650,6 @@ static void cti_device_release(struct device *dev)
|
|||
}
|
||||
mutex_unlock(&ect_mutex);
|
||||
|
||||
if (drvdata->csdev_release)
|
||||
drvdata->csdev_release(dev);
|
||||
}
|
||||
static void cti_remove(struct amba_device *adev)
|
||||
{
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(&adev->dev);
|
||||
|
||||
mutex_lock(&ect_mutex);
|
||||
cti_remove_conn_xrefs(drvdata);
|
||||
mutex_unlock(&ect_mutex);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
}
|
||||
|
||||
|
|
@ -900,29 +695,27 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
return PTR_ERR(pdata);
|
||||
}
|
||||
|
||||
/* default to powered - could change on PM notifications */
|
||||
drvdata->config.hw_powered = true;
|
||||
|
||||
/* set up device name - will depend if cpu bound or otherwise */
|
||||
/*
|
||||
* Set up device name - will depend if cpu bound or otherwise.
|
||||
*
|
||||
* CTI bound to cores will have the name cti_cpu<N> where N is th
|
||||
* eCPU ID. System CTIs will have the name cti_sys<I> where I is an
|
||||
* index allocated by order of discovery.
|
||||
*/
|
||||
if (drvdata->ctidev.cpu >= 0)
|
||||
cti_desc.name = devm_kasprintf(dev, GFP_KERNEL, "cti_cpu%d",
|
||||
drvdata->ctidev.cpu);
|
||||
else
|
||||
cti_desc.name = coresight_alloc_device_name(&cti_sys_devs, dev);
|
||||
cti_desc.name = coresight_alloc_device_name("cti_sys", dev);
|
||||
if (!cti_desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
/* setup CPU power management handling for CPU bound CTI devices. */
|
||||
ret = cti_pm_setup(drvdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* create dynamic attributes for connections */
|
||||
ret = cti_create_cons_sysfs(dev, drvdata);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: create dynamic sysfs entries failed\n",
|
||||
cti_desc.name);
|
||||
goto pm_release;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set up coresight component description */
|
||||
|
|
@ -935,10 +728,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
|
||||
coresight_clear_self_claim_tag(&cti_desc.access);
|
||||
drvdata->csdev = coresight_register(&cti_desc);
|
||||
if (IS_ERR(drvdata->csdev)) {
|
||||
ret = PTR_ERR(drvdata->csdev);
|
||||
goto pm_release;
|
||||
}
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
|
||||
/* add to list of CTI devices */
|
||||
mutex_lock(&ect_mutex);
|
||||
|
|
@ -947,18 +738,10 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
cti_update_conn_xrefs(drvdata);
|
||||
mutex_unlock(&ect_mutex);
|
||||
|
||||
/* set up release chain */
|
||||
drvdata->csdev_release = drvdata->csdev->dev.release;
|
||||
drvdata->csdev->dev.release = cti_device_release;
|
||||
|
||||
/* all done - dec pm refcount */
|
||||
pm_runtime_put(&adev->dev);
|
||||
dev_info(&drvdata->csdev->dev, "CTI initialized\n");
|
||||
return 0;
|
||||
|
||||
pm_release:
|
||||
cti_pm_release(drvdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct amba_cs_uci_id uci_id_cti[] = {
|
||||
|
|
|
|||
|
|
@ -81,19 +81,12 @@ static ssize_t enable_show(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
int enable_req;
|
||||
bool enabled, powered;
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
enable_req = drvdata->config.enable_req_count;
|
||||
powered = drvdata->config.hw_powered;
|
||||
enabled = drvdata->config.hw_enabled;
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
|
||||
enable_req = cti_is_active(&drvdata->config);
|
||||
|
||||
if (powered)
|
||||
return sprintf(buf, "%d\n", enabled);
|
||||
else
|
||||
return sprintf(buf, "%d\n", !!enable_req);
|
||||
return sprintf(buf, "%d\n", !!enable_req);
|
||||
}
|
||||
|
||||
static ssize_t enable_store(struct device *dev,
|
||||
|
|
@ -131,12 +124,7 @@ static ssize_t powered_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
bool powered;
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
powered = drvdata->config.hw_powered;
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
bool powered = pm_runtime_active(dev->parent);
|
||||
|
||||
return sprintf(buf, "%d\n", powered);
|
||||
}
|
||||
|
|
@ -181,10 +169,10 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
|
|||
u32 val = 0;
|
||||
|
||||
pm_runtime_get_sync(dev->parent);
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
if (drvdata->config.hw_powered)
|
||||
val = readl_relaxed(drvdata->base + cti_attr->off);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
|
||||
val = cti_read_single_reg(drvdata, cti_attr->off);
|
||||
|
||||
pm_runtime_put_sync(dev->parent);
|
||||
return sysfs_emit(buf, "0x%x\n", val);
|
||||
}
|
||||
|
|
@ -202,10 +190,10 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
|
|||
return -EINVAL;
|
||||
|
||||
pm_runtime_get_sync(dev->parent);
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
if (drvdata->config.hw_powered)
|
||||
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
|
||||
cti_write_single_reg(drvdata, cti_attr->off, val);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
pm_runtime_put_sync(dev->parent);
|
||||
return size;
|
||||
}
|
||||
|
|
@ -264,17 +252,19 @@ static ssize_t cti_reg32_show(struct device *dev, char *buf,
|
|||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
struct cti_config *config = &drvdata->config;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
if ((reg_offset >= 0) && cti_active(config)) {
|
||||
CS_UNLOCK(drvdata->base);
|
||||
val = readl_relaxed(drvdata->base + reg_offset);
|
||||
if (pcached_val)
|
||||
*pcached_val = val;
|
||||
CS_LOCK(drvdata->base);
|
||||
} else if (pcached_val) {
|
||||
val = *pcached_val;
|
||||
if (reg_offset < 0)
|
||||
return -EINVAL;
|
||||
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
|
||||
if (cti_is_active(config)) {
|
||||
val = cti_read_single_reg(drvdata, reg_offset);
|
||||
if (pcached_val)
|
||||
*pcached_val = val;
|
||||
} else if (pcached_val) {
|
||||
val = *pcached_val;
|
||||
}
|
||||
}
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
return sprintf(buf, "%#x\n", val);
|
||||
}
|
||||
|
||||
|
|
@ -293,15 +283,19 @@ static ssize_t cti_reg32_store(struct device *dev, const char *buf,
|
|||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
/* local store */
|
||||
if (pcached_val)
|
||||
*pcached_val = (u32)val;
|
||||
if (reg_offset < 0)
|
||||
return -EINVAL;
|
||||
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
|
||||
/* local store */
|
||||
if (pcached_val)
|
||||
*pcached_val = (u32)val;
|
||||
|
||||
/* write through if offset and enabled */
|
||||
if (cti_is_active(config))
|
||||
cti_write_single_reg(drvdata, reg_offset, val);
|
||||
}
|
||||
|
||||
/* write through if offset and enabled */
|
||||
if ((reg_offset >= 0) && cti_active(config))
|
||||
cti_write_single_reg(drvdata, reg_offset, val);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
@ -343,15 +337,16 @@ static ssize_t inout_sel_store(struct device *dev,
|
|||
{
|
||||
unsigned long val;
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
struct cti_config *config = &drvdata->config;
|
||||
|
||||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
if (val > (CTIINOUTEN_MAX - 1))
|
||||
if (val >= config->nr_trig_max)
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
drvdata->config.ctiinout_sel = val;
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(inout_sel);
|
||||
|
|
@ -364,10 +359,11 @@ static ssize_t inen_show(struct device *dev,
|
|||
int index;
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
index = drvdata->config.ctiinout_sel;
|
||||
val = drvdata->config.ctiinen[index];
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
|
||||
index = drvdata->config.ctiinout_sel;
|
||||
val = drvdata->config.ctiinen[index];
|
||||
}
|
||||
|
||||
return sprintf(buf, "%#lx\n", val);
|
||||
}
|
||||
|
||||
|
|
@ -383,14 +379,15 @@ static ssize_t inen_store(struct device *dev,
|
|||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
index = config->ctiinout_sel;
|
||||
config->ctiinen[index] = val;
|
||||
|
||||
/* write through if enabled */
|
||||
if (cti_active(config))
|
||||
if (cti_is_active(config))
|
||||
cti_write_single_reg(drvdata, CTIINEN(index), val);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(inen);
|
||||
|
|
@ -403,10 +400,11 @@ static ssize_t outen_show(struct device *dev,
|
|||
int index;
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
index = drvdata->config.ctiinout_sel;
|
||||
val = drvdata->config.ctiouten[index];
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
|
||||
index = drvdata->config.ctiinout_sel;
|
||||
val = drvdata->config.ctiouten[index];
|
||||
}
|
||||
|
||||
return sprintf(buf, "%#lx\n", val);
|
||||
}
|
||||
|
||||
|
|
@ -422,14 +420,15 @@ static ssize_t outen_store(struct device *dev,
|
|||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
index = config->ctiinout_sel;
|
||||
config->ctiouten[index] = val;
|
||||
|
||||
/* write through if enabled */
|
||||
if (cti_active(config))
|
||||
if (cti_is_active(config))
|
||||
cti_write_single_reg(drvdata, CTIOUTEN(index), val);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(outen);
|
||||
|
|
@ -463,15 +462,15 @@ static ssize_t appclear_store(struct device *dev,
|
|||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
/* a 1'b1 in appclr clears down the same bit in appset*/
|
||||
config->ctiappset &= ~val;
|
||||
|
||||
/* write through if enabled */
|
||||
if (cti_active(config))
|
||||
if (cti_is_active(config))
|
||||
cti_write_single_reg(drvdata, CTIAPPCLEAR, val);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_WO(appclear);
|
||||
|
|
@ -487,12 +486,12 @@ static ssize_t apppulse_store(struct device *dev,
|
|||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
/* write through if enabled */
|
||||
if (cti_active(config))
|
||||
if (cti_is_active(config))
|
||||
cti_write_single_reg(drvdata, CTIAPPPULSE, val);
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_WO(apppulse);
|
||||
|
|
@ -530,6 +529,18 @@ static struct attribute *coresight_cti_regs_attrs[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static umode_t coresight_cti_regs_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr, int idx)
|
||||
{
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
if (attr == &dev_attr_asicctl.attr && !drvdata->config.asicctl_impl)
|
||||
return 0;
|
||||
|
||||
return attr->mode;
|
||||
}
|
||||
|
||||
/* CTI channel x-trigger programming */
|
||||
static int
|
||||
cti_trig_op_parse(struct device *dev, enum cti_chan_op op,
|
||||
|
|
@ -681,9 +692,9 @@ static ssize_t trig_filter_enable_show(struct device *dev,
|
|||
u32 val;
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
val = drvdata->config.trig_filter_enable;
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
|
||||
val = drvdata->config.trig_filter_enable;
|
||||
|
||||
return sprintf(buf, "%d\n", val);
|
||||
}
|
||||
|
||||
|
|
@ -697,9 +708,9 @@ static ssize_t trig_filter_enable_store(struct device *dev,
|
|||
if (kstrtoul(buf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
drvdata->config.trig_filter_enable = !!val;
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(trig_filter_enable);
|
||||
|
|
@ -728,7 +739,7 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
|
|||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
struct cti_config *config = &drvdata->config;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
/* clear the CTI trigger / channel programming registers */
|
||||
for (i = 0; i < config->nr_trig_max; i++) {
|
||||
|
|
@ -744,10 +755,9 @@ static ssize_t chan_xtrigs_reset_store(struct device *dev,
|
|||
config->xtrig_rchan_sel = 0;
|
||||
|
||||
/* if enabled then write through */
|
||||
if (cti_active(config))
|
||||
if (cti_is_active(config))
|
||||
cti_write_all_hw_regs(drvdata);
|
||||
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_WO(chan_xtrigs_reset);
|
||||
|
|
@ -768,9 +778,9 @@ static ssize_t chan_xtrigs_sel_store(struct device *dev,
|
|||
if (val > (drvdata->config.nr_ctm_channels - 1))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
|
||||
|
||||
drvdata->config.xtrig_rchan_sel = val;
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
@ -781,9 +791,8 @@ static ssize_t chan_xtrigs_sel_show(struct device *dev,
|
|||
unsigned long val;
|
||||
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
val = drvdata->config.xtrig_rchan_sel;
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
|
||||
val = drvdata->config.xtrig_rchan_sel;
|
||||
|
||||
return sprintf(buf, "%ld\n", val);
|
||||
}
|
||||
|
|
@ -838,12 +847,12 @@ static ssize_t print_chan_list(struct device *dev,
|
|||
unsigned long inuse_bits = 0, chan_mask;
|
||||
|
||||
/* scan regs to get bitmap of channels in use. */
|
||||
raw_spin_lock(&drvdata->spinlock);
|
||||
for (i = 0; i < config->nr_trig_max; i++) {
|
||||
inuse_bits |= config->ctiinen[i];
|
||||
inuse_bits |= config->ctiouten[i];
|
||||
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock) {
|
||||
for (i = 0; i < config->nr_trig_max; i++) {
|
||||
inuse_bits |= config->ctiinen[i];
|
||||
inuse_bits |= config->ctiouten[i];
|
||||
}
|
||||
}
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
/* inverse bits if printing free channels */
|
||||
if (!inuse)
|
||||
|
|
@ -1169,6 +1178,7 @@ static const struct attribute_group coresight_cti_mgmt_group = {
|
|||
|
||||
static const struct attribute_group coresight_cti_regs_group = {
|
||||
.attrs = coresight_cti_regs_attrs,
|
||||
.is_visible = coresight_cti_regs_is_visible,
|
||||
.name = "regs",
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -119,9 +119,8 @@ struct cti_device {
|
|||
* @nr_trig_max: Max number of trigger signals implemented on device.
|
||||
* (max of trig_in or trig_out) - from ID register.
|
||||
* @nr_ctm_channels: number of available CTM channels - from ID register.
|
||||
* @asicctl_impl: true if asicctl is implemented.
|
||||
* @enable_req_count: CTI is enabled alongside >=1 associated devices.
|
||||
* @hw_enabled: true if hw is currently enabled.
|
||||
* @hw_powered: true if associated cpu powered on, or no cpu.
|
||||
* @trig_in_use: bitfield of in triggers registered as in use.
|
||||
* @trig_out_use: bitfield of out triggers registered as in use.
|
||||
* @trig_out_filter: bitfield of out triggers that are blocked if filter
|
||||
|
|
@ -140,11 +139,10 @@ struct cti_config {
|
|||
/* hardware description */
|
||||
int nr_ctm_channels;
|
||||
int nr_trig_max;
|
||||
bool asicctl_impl;
|
||||
|
||||
/* cti enable control */
|
||||
int enable_req_count;
|
||||
bool hw_enabled;
|
||||
bool hw_powered;
|
||||
|
||||
/* registered triggers and filtering */
|
||||
u32 trig_in_use;
|
||||
|
|
@ -170,7 +168,6 @@ struct cti_config {
|
|||
* @spinlock: Control data access to one at a time.
|
||||
* @config: Configuration data for this CTI device.
|
||||
* @node: List entry of this device in the list of CTI devices.
|
||||
* @csdev_release: release function for underlying coresight_device.
|
||||
*/
|
||||
struct cti_drvdata {
|
||||
void __iomem *base;
|
||||
|
|
@ -179,7 +176,6 @@ struct cti_drvdata {
|
|||
raw_spinlock_t spinlock;
|
||||
struct cti_config config;
|
||||
struct list_head node;
|
||||
void (*csdev_release)(struct device *dev);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -222,6 +218,7 @@ int cti_disable(struct coresight_device *csdev, struct coresight_path *path);
|
|||
void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
|
||||
void cti_write_intack(struct device *dev, u32 ackval);
|
||||
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
|
||||
u32 cti_read_single_reg(struct cti_drvdata *drvdata, int offset);
|
||||
int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
|
||||
enum cti_trig_dir direction, u32 channel_idx,
|
||||
u32 trigger_idx);
|
||||
|
|
@ -234,10 +231,10 @@ struct coresight_platform_data *
|
|||
coresight_cti_get_platform_data(struct device *dev);
|
||||
const char *cti_plat_get_node_name(struct fwnode_handle *fwnode);
|
||||
|
||||
/* cti powered and enabled */
|
||||
static inline bool cti_active(struct cti_config *cfg)
|
||||
/* Check if a cti device is enabled */
|
||||
static inline bool cti_is_active(struct cti_config *cfg)
|
||||
{
|
||||
return cfg->hw_powered && cfg->hw_enabled;
|
||||
return !!cfg->enable_req_count;
|
||||
}
|
||||
|
||||
#endif /* _CORESIGHT_CORESIGHT_CTI_H */
|
||||
|
|
|
|||
|
|
@ -19,9 +19,6 @@ struct dummy_drvdata {
|
|||
u8 traceid;
|
||||
};
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source");
|
||||
DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink");
|
||||
|
||||
static int dummy_source_enable(struct coresight_device *csdev,
|
||||
struct perf_event *event, enum cs_mode mode,
|
||||
__maybe_unused struct coresight_path *path)
|
||||
|
|
@ -126,7 +123,7 @@ static int dummy_probe(struct platform_device *pdev)
|
|||
|
||||
if (of_device_is_compatible(node, "arm,coresight-dummy-source")) {
|
||||
|
||||
desc.name = coresight_alloc_device_name(&source_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("dummy_source", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -155,7 +152,7 @@ static int dummy_probe(struct platform_device *pdev)
|
|||
drvdata->traceid = (u8)trace_id;
|
||||
|
||||
} else if (of_device_is_compatible(node, "arm,coresight-dummy-sink")) {
|
||||
desc.name = coresight_alloc_device_name(&sink_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("dummy_sink", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -63,8 +63,6 @@
|
|||
#define ETB_FFSR_BIT 1
|
||||
#define ETB_FRAME_SIZE_WORDS 4
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(etb_devs, "etb");
|
||||
|
||||
/**
|
||||
* struct etb_drvdata - specifics associated to an ETB component
|
||||
* @base: memory mapped base address for this component.
|
||||
|
|
@ -722,7 +720,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
struct resource *res = &adev->res;
|
||||
struct coresight_desc desc = { 0 };
|
||||
|
||||
desc.name = coresight_alloc_device_name(&etb_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("etb", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -902,7 +902,10 @@ int etm_perf_add_symlink_sink(struct coresight_device *csdev)
|
|||
|
||||
if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
|
||||
csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
|
||||
return -EINVAL;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!sink_ops(csdev)->alloc_buffer)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (csdev->ea != NULL)
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@
|
|||
#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
|
||||
#define FUNNEL_ENSx_MASK 0xff
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(funnel_devs, "funnel");
|
||||
|
||||
/**
|
||||
* struct funnel_drvdata - specifics associated to a funnel component
|
||||
* @base: memory mapped base address for this component.
|
||||
|
|
@ -223,7 +221,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
|
|||
of_device_is_compatible(dev->of_node, "arm,coresight-funnel"))
|
||||
dev_warn_once(dev, "Uses OBSOLETE CoreSight funnel binding\n");
|
||||
|
||||
desc.name = coresight_alloc_device_name(&funnel_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("funnel", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -220,6 +220,8 @@ static int of_coresight_parse_endpoint(struct device *dev,
|
|||
rparent = of_coresight_get_port_parent(rep);
|
||||
if (!rparent)
|
||||
break;
|
||||
if (!of_device_is_available(rparent))
|
||||
break;
|
||||
if (of_graph_parse_endpoint(rep, &rendpoint))
|
||||
break;
|
||||
|
||||
|
|
@ -849,7 +851,7 @@ coresight_get_platform_data(struct device *dev)
|
|||
error:
|
||||
if (!IS_ERR_OR_NULL(pdata))
|
||||
/* Cleanup the connection information */
|
||||
coresight_release_platform_data(NULL, dev, pdata);
|
||||
coresight_release_platform_data(dev, pdata);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_get_platform_data);
|
||||
|
|
|
|||
|
|
@ -239,8 +239,7 @@ static inline void *coresight_get_uci_data_from_amba(const struct amba_id *table
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void coresight_release_platform_data(struct coresight_device *csdev,
|
||||
struct device *dev,
|
||||
void coresight_release_platform_data(struct device *dev,
|
||||
struct coresight_platform_data *pdata);
|
||||
struct coresight_device *
|
||||
coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode);
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@
|
|||
#define REPLICATOR_IDFILTER0 0x000
|
||||
#define REPLICATOR_IDFILTER1 0x004
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(replicator_devs, "replicator");
|
||||
|
||||
/**
|
||||
* struct replicator_drvdata - specifics associated to a replicator component
|
||||
* @base: memory mapped base address for this component. Also indicates
|
||||
|
|
@ -230,7 +228,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
|
|||
dev_warn_once(dev,
|
||||
"Uses OBSOLETE CoreSight replicator binding\n");
|
||||
|
||||
desc.name = coresight_alloc_device_name(&replicator_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("replicator", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -110,8 +110,6 @@ struct channel_space {
|
|||
unsigned long *guaranteed;
|
||||
};
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm");
|
||||
|
||||
/**
|
||||
* struct stm_drvdata - specifics associated to an STM component
|
||||
* @base: memory mapped base address for this component.
|
||||
|
|
@ -834,7 +832,7 @@ static int __stm_probe(struct device *dev, struct resource *res)
|
|||
struct resource ch_res;
|
||||
struct coresight_desc desc = { 0 };
|
||||
|
||||
desc.name = coresight_alloc_device_name(&stm_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("stm", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,10 +32,6 @@
|
|||
#include "coresight-priv.h"
|
||||
#include "coresight-tmc.h"
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(etb_devs, "tmc_etb");
|
||||
DEFINE_CORESIGHT_DEVLIST(etf_devs, "tmc_etf");
|
||||
DEFINE_CORESIGHT_DEVLIST(etr_devs, "tmc_etr");
|
||||
|
||||
int tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
struct coresight_device *csdev = drvdata->csdev;
|
||||
|
|
@ -401,7 +397,6 @@ static ssize_t tmc_crashdata_read(struct file *file, char __user *data,
|
|||
|
||||
static int tmc_crashdata_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
struct tmc_resrv_buf *rbuf;
|
||||
struct tmc_drvdata *drvdata = container_of(file->private_data,
|
||||
|
|
@ -414,7 +409,7 @@ static int tmc_crashdata_release(struct inode *inode, struct file *file)
|
|||
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
dev_dbg(&drvdata->csdev->dev, "%s: released\n", __func__);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations tmc_crashdata_fops = {
|
||||
|
|
@ -777,7 +772,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
|
|||
struct coresight_platform_data *pdata = NULL;
|
||||
struct tmc_drvdata *drvdata;
|
||||
struct coresight_desc desc = { 0 };
|
||||
struct coresight_dev_list *dev_list = NULL;
|
||||
const char *dev_list = NULL;
|
||||
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
|
|
@ -827,7 +822,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
|
|||
desc.type = CORESIGHT_DEV_TYPE_SINK;
|
||||
desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
|
||||
desc.ops = &tmc_etb_cs_ops;
|
||||
dev_list = &etb_devs;
|
||||
dev_list = "tmc_etb";
|
||||
break;
|
||||
case TMC_CONFIG_TYPE_ETR:
|
||||
desc.groups = coresight_etr_groups;
|
||||
|
|
@ -839,7 +834,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
|
|||
goto out;
|
||||
idr_init(&drvdata->idr);
|
||||
mutex_init(&drvdata->idr_mutex);
|
||||
dev_list = &etr_devs;
|
||||
dev_list = "tmc_etr";
|
||||
break;
|
||||
case TMC_CONFIG_TYPE_ETF:
|
||||
desc.groups = coresight_etf_groups;
|
||||
|
|
@ -847,7 +842,7 @@ static int __tmc_probe(struct device *dev, struct resource *res)
|
|||
desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
|
||||
desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
|
||||
desc.ops = &tmc_etf_cs_ops;
|
||||
dev_list = &etf_devs;
|
||||
dev_list = "tmc_etf";
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Unsupported TMC config\n", desc.name);
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ struct trace_noc_drvdata {
|
|||
int atid;
|
||||
};
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(trace_noc_devs, "traceNoc");
|
||||
|
||||
static void trace_noc_enable_hw(struct trace_noc_drvdata *drvdata)
|
||||
{
|
||||
u32 val;
|
||||
|
|
@ -191,7 +189,7 @@ static int _tnoc_probe(struct device *dev, struct resource *res)
|
|||
struct coresight_desc desc = { 0 };
|
||||
int ret;
|
||||
|
||||
desc.name = coresight_alloc_device_name(&trace_noc_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("traceNoc", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@
|
|||
#include "coresight-trace-id.h"
|
||||
#include "coresight-tpdm.h"
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
|
||||
|
||||
static void tpda_clear_element_size(struct coresight_device *csdev)
|
||||
{
|
||||
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
|
@ -585,7 +583,7 @@ static int tpda_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
desc.name = coresight_alloc_device_name(&tpda_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("tpda", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
desc.type = CORESIGHT_DEV_TYPE_LINK;
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@
|
|||
#include "coresight-priv.h"
|
||||
#include "coresight-tpdm.h"
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(tpdm_devs, "tpdm");
|
||||
|
||||
static bool tpdm_has_dsb_dataset(struct tpdm_drvdata *drvdata)
|
||||
{
|
||||
return (drvdata->datasets & TPDM_PIDR0_DS_DSB);
|
||||
|
|
@ -483,7 +481,7 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
|
|||
|
||||
static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
enum cs_mode mode,
|
||||
__maybe_unused struct coresight_path *path)
|
||||
struct coresight_path *path)
|
||||
{
|
||||
struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
|
|
@ -499,6 +497,7 @@ static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
|
|||
}
|
||||
|
||||
__tpdm_enable(drvdata);
|
||||
drvdata->traceid = path->trace_id;
|
||||
drvdata->enable = true;
|
||||
spin_unlock(&drvdata->spinlock);
|
||||
|
||||
|
|
@ -695,6 +694,29 @@ static struct attribute_group tpdm_attr_grp = {
|
|||
.attrs = tpdm_attrs,
|
||||
};
|
||||
|
||||
static ssize_t traceid_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned long val;
|
||||
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
val = drvdata->traceid;
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
return sysfs_emit(buf, "%#lx\n", val);
|
||||
}
|
||||
static DEVICE_ATTR_RO(traceid);
|
||||
|
||||
static struct attribute *traceid_attrs[] = {
|
||||
&dev_attr_traceid.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group traceid_attr_grp = {
|
||||
.attrs = traceid_attrs,
|
||||
};
|
||||
|
||||
static ssize_t dsb_mode_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
|
|
@ -1369,6 +1391,12 @@ static const struct attribute_group *tpdm_attr_grps[] = {
|
|||
&tpdm_cmb_patt_grp,
|
||||
&tpdm_cmb_msr_grp,
|
||||
&tpdm_mcmb_attr_grp,
|
||||
&traceid_attr_grp,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group *static_tpdm_attr_grps[] = {
|
||||
&traceid_attr_grp,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
@ -1402,6 +1430,7 @@ static int tpdm_probe(struct device *dev, struct resource *res)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||
if (tpdm_has_dsb_dataset(drvdata))
|
||||
of_property_read_u32(drvdata->dev->of_node,
|
||||
"qcom,dsb-msrs-num", &drvdata->dsb_msr_num);
|
||||
|
|
@ -1416,7 +1445,7 @@ static int tpdm_probe(struct device *dev, struct resource *res)
|
|||
}
|
||||
|
||||
/* Set up coresight component description */
|
||||
desc.name = coresight_alloc_device_name(&tpdm_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("tpdm", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
desc.type = CORESIGHT_DEV_TYPE_SOURCE;
|
||||
|
|
@ -1424,9 +1453,10 @@ static int tpdm_probe(struct device *dev, struct resource *res)
|
|||
desc.ops = &tpdm_cs_ops;
|
||||
desc.pdata = dev->platform_data;
|
||||
desc.dev = dev;
|
||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||
if (res)
|
||||
desc.groups = tpdm_attr_grps;
|
||||
else
|
||||
desc.groups = static_tpdm_attr_grps;
|
||||
drvdata->csdev = coresight_register(&desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
|
|
|
|||
|
|
@ -300,6 +300,7 @@ struct cmb_dataset {
|
|||
* @cmb Specifics associated to TPDM CMB.
|
||||
* @dsb_msr_num Number of MSR supported by DSB TPDM
|
||||
* @cmb_msr_num Number of MSR supported by CMB TPDM
|
||||
* @traceid Trace ID of the path.
|
||||
*/
|
||||
|
||||
struct tpdm_drvdata {
|
||||
|
|
@ -313,6 +314,7 @@ struct tpdm_drvdata {
|
|||
struct cmb_dataset *cmb;
|
||||
u32 dsb_msr_num;
|
||||
u32 cmb_msr_num;
|
||||
u8 traceid;
|
||||
};
|
||||
|
||||
/* Enumerate members of various datasets */
|
||||
|
|
|
|||
|
|
@ -49,8 +49,6 @@
|
|||
#define FFCR_FON_MAN BIT(6)
|
||||
#define FFCR_STOP_FI BIT(12)
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(tpiu_devs, "tpiu");
|
||||
|
||||
/*
|
||||
* @base: memory mapped base address for this component.
|
||||
* @atclk: optional clock for the core parts of the TPIU.
|
||||
|
|
@ -134,7 +132,7 @@ static int __tpiu_probe(struct device *dev, struct resource *res)
|
|||
struct coresight_desc desc = { 0 };
|
||||
int ret;
|
||||
|
||||
desc.name = coresight_alloc_device_name(&tpiu_devs, dev);
|
||||
desc.name = coresight_alloc_device_name("tpiu", dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@
|
|||
#include "coresight-priv.h"
|
||||
#include "ultrasoc-smb.h"
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(sink_devs, "ultra_smb");
|
||||
|
||||
#define ULTRASOC_SMB_DSM_UUID "82ae1283-7f6a-4cbe-aa06-53e8fb24db18"
|
||||
|
||||
static bool smb_buffer_not_empty(struct smb_drv_data *drvdata)
|
||||
|
|
@ -478,7 +476,7 @@ static int smb_register_sink(struct platform_device *pdev,
|
|||
desc.pdata = pdata;
|
||||
desc.dev = &pdev->dev;
|
||||
desc.groups = smb_sink_groups;
|
||||
desc.name = coresight_alloc_device_name(&sink_devs, &pdev->dev);
|
||||
desc.name = coresight_alloc_device_name("ultra_smb", &pdev->dev);
|
||||
if (!desc.name) {
|
||||
dev_err(&pdev->dev, "Failed to alloc coresight device name");
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -306,24 +306,19 @@ struct coresight_device {
|
|||
* coresight_dev_list - Mapping for devices to "name" index for device
|
||||
* names.
|
||||
*
|
||||
* @node: Node on the global device index list.
|
||||
* @nr_idx: Number of entries already allocated.
|
||||
* @pfx: Prefix pattern for device name.
|
||||
* @fwnode_list: Array of fwnode_handles associated with each allocated
|
||||
* index, upto nr_idx entries.
|
||||
*/
|
||||
struct coresight_dev_list {
|
||||
struct list_head node;
|
||||
int nr_idx;
|
||||
const char *pfx;
|
||||
char *pfx;
|
||||
struct fwnode_handle **fwnode_list;
|
||||
};
|
||||
|
||||
#define DEFINE_CORESIGHT_DEVLIST(var, dev_pfx) \
|
||||
static struct coresight_dev_list (var) = { \
|
||||
.pfx = dev_pfx, \
|
||||
.nr_idx = 0, \
|
||||
.fwnode_list = NULL, \
|
||||
}
|
||||
|
||||
#define to_coresight_device(d) container_of(d, struct coresight_device, dev)
|
||||
|
||||
/**
|
||||
|
|
@ -663,8 +658,7 @@ void coresight_clear_self_claim_tag(struct csdev_access *csa);
|
|||
void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa);
|
||||
void coresight_disclaim_device(struct coresight_device *csdev);
|
||||
void coresight_disclaim_device_unlocked(struct coresight_device *csdev);
|
||||
char *coresight_alloc_device_name(struct coresight_dev_list *devs,
|
||||
struct device *dev);
|
||||
char *coresight_alloc_device_name(const char *prefix, struct device *dev);
|
||||
|
||||
bool coresight_loses_context_with_cpu(struct device *dev);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user