* [PATCH v10 0/5] Add Qualcomm extended CTI support
@ 2026-06-15 12:32 Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 1/5] coresight: cti: Convert trigger usage fields to dynamic Yingchao Deng
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Yingchao Deng @ 2026-06-15 12:32 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, quic_yingdeng,
tingwei.zhang, Jinlong Mao, jie.gan, Yingchao Deng
The Qualcomm extended CTI is a heavily parameterized version of ARM’s
CSCTI. It allows a debugger to send to trigger events to a processor or to
send a trigger event to one or more processors when a trigger event occurs
on another processor on the same SoC, or even between SoCs.
Qualcomm extended CTI supports up to 128 triggers. And some of the register
offsets are changed.
The commands to configure CTI triggers are the same as ARM's CTI.
Changes in v10:
1. rebase on top of linux-next-20260609.
2. patch 1: Add a bounds check in cti_allocate_trig_con() to guard
against in_sigs / out_sigs exceeding nr_trig_max; carry forward
Reviewed-by tag from v8/v9.
3. patch 2: Move __reg_addr(), cti_read/write_single_reg() helpers into
coresight-cti.h as static inlines; add cti_read/write_single_reg_index()
variants.
4. patch 3: Replace the direct CLAIMSET clear-to-zero with thin wrapper
helpers (cti_claim_device, cti_disclaim_device_unlocked,
cti_clear_self_claim_tag) that early-return when is_qcom_cti is set,
bypassing claim operations entirely for Qualcomm CTIs. Fold qcom-cti.h
into coresight-cti.h
5. patch 4: Add Reviewed-by tag.
6. patch 5: New patch. Document the banked trigger status and integration
test registers added in patch 4 (triginstatus[1-3], trigoutstatus[1-3],
ittrigin[1-3], ittrigout[1-3], ittrigoutack[1-3], ittriginack[1-3]).
Also document the previously undocumented base integration test
registers (itctrl, itchin, itchinack, ittrigin, ittriginack, itchout,
itchoutack, ittrigout, ittrigoutack) introduced in kernel 5.7.
Changes in v9:
1. rebase on top of linux-next-20260518.
2. patch 2: Replace the "encode index into offset high bits" scheme with a cleaner
__reg_addr(drvdata, off, index) helper; update cti_read/write_single_reg() to
take separate off and index arguments; add u32 index field to cs_off_attribute
(moved to coresight-priv.h); drop CTI_REG_SET/GET/CLR_NR macros and
<linux/bitfield.h>; update commit subject accordingly.
3. patch 4: Add three index-aware sysfs macros (coresight_cti_reg_index,
_rw_index, _wo_index); replace string-matching visibility logic with
cs_off_attribute.index field check;
Link to v8 - https://lore.kernel.org/all/20260426-extended-cti-v8-0-23b900a4902f@oss.qualcomm.com/
Changes in v8:
1. Rebased on top of linux-next-20260424.
2. patch 1: Use devm_bitmap_zalloc() with nr_trig_max instead of per-connection
signal counts; add bitmap_zalloc() for filter trigger group.
3. patch 2: Add #include <linux/bitfield.h>; move CTIINOUTEN_MAX expansion
to patch3.
4. patch 3: wrap CLAIMSET clear with CS_UNLOCK/CS_LOCK; move CTIINOUTEN_MAX
to 128 here with comment; fix macro alignment in qcom-cti.h.
5. patch 4: Make qcom_suffix_registers[] static.
Link to v7 - https://lore.kernel.org/all/20260325-extended_cti-v7-0-bb406005089f@oss.qualcomm.com/
Changes in v7:
1. Split the extended CTI support into smaller, logically independent
patches to improve reviewability.
2. Removed the dual offset-array based register access used in v6 for
standard and Qualcomm CTIs. Register addressing is now unified through
a single code path by encoding the register index together with the base
offset and applying variant-specific translation at the final MMIO
access point.
3. Removed ext_reg_sel, extend the CTI sysfs interface to expose banked
register instances on Qualcomm CTIs only. Numbered sysfs nodes are
hidden on standard ARM CTIs, and on Qualcomm CTIs their visibility is
derived from nr_trig_max (32 triggers per bank), ensuring that only
registers backed by hardware are exposed.
Link to v6 - https://lore.kernel.org/all/20251202-extended_cti-v6-0-ab68bb15c4f5@oss.qualcomm.com/
Changes in v6:
1. Rename regs_idx to ext_reg_sel and add information in documentation
file.
2. Reset CLAIMSET to zero for qcom-cti during probe.
3. Retrieve idx value under spinlock.
4. Use yearless copyright for qcom-cti.h.
Link to v5 - https://lore.kernel.org/all/20251020-extended_cti-v5-0-6f193da2d467@oss.qualcomm.com/
Changes in v5:
1. Move common part in qcom-cti.h to coresight-cti.h.
2. Convert trigger usage fields to dynamic bitmaps and arrays.
3. Fix holes in struct cti_config to save some space.
4. Revert the previous changes related to the claim tag in
cti_enable/disable_hw.
Link to v4 - https://lore.kernel.org/linux-arm-msm/20250902-extended_cti-v4-1-7677de04b416@oss.qualcomm.com/
Changes in v4:
1. Read the DEVARCH registers to identify Qualcomm CTI.
2. Add a reg_idx node, and refactor the coresight_cti_reg_show() and
coresight_cti_reg_store() functions accordingly.
3. The register offsets specific to Qualcomm CTI are moved to qcom_cti.h.
Link to v3 - https://lore.kernel.org/linux-arm-msm/20250722081405.2947294-1-quic_jinlmao@quicinc.com/
Changes in v3:
1. Rename is_extended_cti() to of_is_extended_cti().
2. Add the missing 'i' when write the CTI trigger registers.
3. Convert the multi-line output in sysfs to single line.
4. Initialize offset arrays using designated initializer.
Link to V2 - https://lore.kernel.org/all/20250429071841.1158315-3-quic_jinlmao@quicinc.com/
Changes in V2:
1. Add enum for compatible items.
2. Move offset arrays to coresight-cti-core
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
Yingchao Deng (5):
coresight: cti: Convert trigger usage fields to dynamic
coresight: cti: use __reg_addr() helper for register access
coresight: cti: add Qualcomm extended CTI identification and quirks
coresight: cti: expose banked sysfs registers for Qualcomm extended CTI
coresight: cti: document banked and missing base CTI sysfs registers
.../ABI/testing/sysfs-bus-coresight-devices-cti | 90 ++++++++++++
drivers/hwtracing/coresight/coresight-cti-core.c | 153 ++++++++++++++-------
.../hwtracing/coresight/coresight-cti-platform.c | 26 ++--
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 89 ++++++++++--
drivers/hwtracing/coresight/coresight-cti.h | 122 ++++++++++++++--
drivers/hwtracing/coresight/coresight-priv.h | 4 +-
6 files changed, 404 insertions(+), 80 deletions(-)
---
base-commit: 49e02880ec0a8c378e811bc9d85da188d7c6204c
change-id: 20260611-extended_cti-dd4971ef98fa
Best regards,
--
Yingchao Deng <yingchao.deng@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v10 1/5] coresight: cti: Convert trigger usage fields to dynamic
2026-06-15 12:32 [PATCH v10 0/5] Add Qualcomm extended CTI support Yingchao Deng
@ 2026-06-15 12:32 ` Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 2/5] coresight: cti: use __reg_addr() helper for register access Yingchao Deng
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Yingchao Deng @ 2026-06-15 12:32 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, quic_yingdeng,
tingwei.zhang, Jinlong Mao, jie.gan, Yingchao Deng
Replace the fixed-size u32 fields in the cti_config and cti_trig_grp
structure with dynamically allocated bitmaps and arrays. This allows
memory to be allocated based on the actual number of triggers during probe
time, reducing memory footprint and improving scalability for platforms
with varying trigger counts.
Also add a bounds check in cti_allocate_trig_con() to ensure the caller
does not pass in/out signal counts larger than nr_trig_max.
Reviewed-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-cti-core.c | 70 +++++++++++++++++-----
.../hwtracing/coresight/coresight-cti-platform.c | 26 +++++---
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 14 ++---
drivers/hwtracing/coresight/coresight-cti.h | 12 ++--
4 files changed, 87 insertions(+), 35 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index b2c9a4db13b4..572798ab504c 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -161,8 +161,8 @@ void cti_write_intack(struct device *dev, u32 ackval)
/* DEVID[19:16] - number of CTM channels */
#define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19))
-static void cti_set_default_config(struct device *dev,
- struct cti_drvdata *drvdata)
+static int cti_set_default_config(struct device *dev,
+ struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
u32 devid;
@@ -181,6 +181,31 @@ static void cti_set_default_config(struct device *dev,
config->nr_trig_max = CTIINOUTEN_MAX;
}
+ config->trig_in_use = devm_bitmap_zalloc(dev, config->nr_trig_max,
+ GFP_KERNEL);
+ if (!config->trig_in_use)
+ return -ENOMEM;
+
+ config->trig_out_use = devm_bitmap_zalloc(dev, config->nr_trig_max,
+ GFP_KERNEL);
+ if (!config->trig_out_use)
+ return -ENOMEM;
+
+ config->trig_out_filter = devm_bitmap_zalloc(dev, config->nr_trig_max,
+ GFP_KERNEL);
+ if (!config->trig_out_filter)
+ return -ENOMEM;
+
+ config->ctiinen = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32),
+ GFP_KERNEL);
+ if (!config->ctiinen)
+ return -ENOMEM;
+
+ config->ctiouten = devm_kcalloc(dev, config->nr_trig_max, sizeof(u32),
+ GFP_KERNEL);
+ if (!config->ctiouten)
+ return -ENOMEM;
+
config->nr_ctm_channels = CTI_DEVID_CTMCHANNELS(devid);
/* Most regs default to 0 as zalloc'ed except...*/
@@ -189,6 +214,7 @@ static void cti_set_default_config(struct device *dev,
config->enable_req_count = 0;
config->asicctl_impl = !!FIELD_GET(GENMASK(4, 0), devid);
+ return 0;
}
/*
@@ -219,8 +245,10 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
cti_dev->nr_trig_con++;
/* add connection usage bit info to overall info */
- drvdata->config.trig_in_use |= tc->con_in->used_mask;
- drvdata->config.trig_out_use |= tc->con_out->used_mask;
+ bitmap_or(drvdata->config.trig_in_use, drvdata->config.trig_in_use,
+ tc->con_in->used_mask, drvdata->config.nr_trig_max);
+ bitmap_or(drvdata->config.trig_out_use, drvdata->config.trig_out_use,
+ tc->con_out->used_mask, drvdata->config.nr_trig_max);
return 0;
}
@@ -231,6 +259,14 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
{
struct cti_trig_con *tc = NULL;
struct cti_trig_grp *in = NULL, *out = NULL;
+ struct cti_drvdata *drvdata = dev_get_drvdata(dev);
+ int n_trigs = drvdata->config.nr_trig_max;
+
+ if (in_sigs > n_trigs || out_sigs > n_trigs) {
+ dev_err(dev, "trigger signal is out of range: in=%d out=%d nr_max=%d\n",
+ in_sigs, out_sigs, n_trigs);
+ return NULL;
+ }
tc = devm_kzalloc(dev, sizeof(struct cti_trig_con), GFP_KERNEL);
if (!tc)
@@ -242,12 +278,20 @@ struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
if (!in)
return NULL;
+ in->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL);
+ if (!in->used_mask)
+ return NULL;
+
out = devm_kzalloc(dev,
offsetof(struct cti_trig_grp, sig_types[out_sigs]),
GFP_KERNEL);
if (!out)
return NULL;
+ out->used_mask = devm_bitmap_zalloc(dev, n_trigs, GFP_KERNEL);
+ if (!out->used_mask)
+ return NULL;
+
tc->con_in = in;
tc->con_out = out;
tc->con_in->nr_sigs = in_sigs;
@@ -263,7 +307,6 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
{
int ret = 0;
int n_trigs = drvdata->config.nr_trig_max;
- u32 n_trig_mask = GENMASK(n_trigs - 1, 0);
struct cti_trig_con *tc = NULL;
/*
@@ -274,8 +317,8 @@ int cti_add_default_connection(struct device *dev, struct cti_drvdata *drvdata)
if (!tc)
return -ENOMEM;
- tc->con_in->used_mask = n_trig_mask;
- tc->con_out->used_mask = n_trig_mask;
+ bitmap_fill(tc->con_in->used_mask, n_trigs);
+ bitmap_fill(tc->con_out->used_mask, n_trigs);
ret = cti_add_connection_entry(dev, drvdata, tc, NULL, "default");
return ret;
}
@@ -288,7 +331,6 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
{
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *config = &drvdata->config;
- u32 trig_bitmask;
u32 chan_bitmask;
u32 reg_value;
int reg_offset;
@@ -298,18 +340,16 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
(trigger_idx >= config->nr_trig_max))
return -EINVAL;
- trig_bitmask = BIT(trigger_idx);
-
/* ensure registered triggers and not out filtered */
if (direction == CTI_TRIG_IN) {
- if (!(trig_bitmask & config->trig_in_use))
+ if (!(test_bit(trigger_idx, config->trig_in_use)))
return -EINVAL;
} else {
- if (!(trig_bitmask & config->trig_out_use))
+ if (!(test_bit(trigger_idx, config->trig_out_use)))
return -EINVAL;
if ((config->trig_filter_enable) &&
- (config->trig_out_filter & trig_bitmask))
+ test_bit(trigger_idx, config->trig_out_filter))
return -EINVAL;
}
@@ -687,7 +727,9 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
raw_spin_lock_init(&drvdata->spinlock);
/* initialise CTI driver config values */
- cti_set_default_config(dev, drvdata);
+ ret = cti_set_default_config(dev, drvdata);
+ if (ret)
+ return ret;
pdata = coresight_cti_get_platform_data(dev);
if (IS_ERR(pdata)) {
diff --git a/drivers/hwtracing/coresight/coresight-cti-platform.c b/drivers/hwtracing/coresight/coresight-cti-platform.c
index d6d5388705c3..ba5a7e4b6bff 100644
--- a/drivers/hwtracing/coresight/coresight-cti-platform.c
+++ b/drivers/hwtracing/coresight/coresight-cti-platform.c
@@ -136,8 +136,8 @@ static int cti_plat_create_v8_etm_connection(struct device *dev,
goto create_v8_etm_out;
/* build connection data */
- tc->con_in->used_mask = 0xF0; /* sigs <4,5,6,7> */
- tc->con_out->used_mask = 0xF0; /* sigs <4,5,6,7> */
+ bitmap_set(tc->con_in->used_mask, 4, 4); /* sigs <4,5,6,7> */
+ bitmap_set(tc->con_out->used_mask, 4, 4); /* sigs <4,5,6,7> */
/*
* The EXTOUT type signals from the ETM are connected to a set of input
@@ -194,10 +194,10 @@ static int cti_plat_create_v8_connections(struct device *dev,
goto of_create_v8_out;
/* Set the v8 PE CTI connection data */
- tc->con_in->used_mask = 0x3; /* sigs <0 1> */
+ bitmap_set(tc->con_in->used_mask, 0, 2); /* sigs <0 1> */
tc->con_in->sig_types[0] = PE_DBGTRIGGER;
tc->con_in->sig_types[1] = PE_PMUIRQ;
- tc->con_out->used_mask = 0x7; /* sigs <0 1 2 > */
+ bitmap_set(tc->con_out->used_mask, 0, 3); /* sigs <0 1 2 > */
tc->con_out->sig_types[0] = PE_EDBGREQ;
tc->con_out->sig_types[1] = PE_DBGRESTART;
tc->con_out->sig_types[2] = PE_CTIIRQ;
@@ -213,7 +213,7 @@ static int cti_plat_create_v8_connections(struct device *dev,
goto of_create_v8_out;
/* filter pe_edbgreq - PE trigout sig <0> */
- drvdata->config.trig_out_filter |= 0x1;
+ set_bit(0, drvdata->config.trig_out_filter);
of_create_v8_out:
return ret;
@@ -257,7 +257,7 @@ static int cti_plat_read_trig_group(struct cti_trig_grp *tgrp,
if (!err) {
/* set the signal usage mask */
for (idx = 0; idx < tgrp->nr_sigs; idx++)
- tgrp->used_mask |= BIT(values[idx]);
+ set_bit(values[idx], tgrp->used_mask);
}
kfree(values);
@@ -316,24 +316,34 @@ static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata,
{
struct cti_trig_grp *tg = NULL;
int err = 0, nr_filter_sigs;
+ int nr_trigs = drvdata->config.nr_trig_max;
nr_filter_sigs = cti_plat_count_sig_elements(fwnode,
CTI_DT_FILTER_OUT_SIGS);
if (nr_filter_sigs == 0)
return 0;
- if (nr_filter_sigs > drvdata->config.nr_trig_max)
+ if (nr_filter_sigs > nr_trigs)
return -EINVAL;
tg = kzalloc_obj(*tg);
if (!tg)
return -ENOMEM;
+ tg->used_mask = bitmap_zalloc(nr_trigs, GFP_KERNEL);
+ if (!tg->used_mask) {
+ kfree(tg);
+ return -ENOMEM;
+ }
+
tg->nr_sigs = nr_filter_sigs;
err = cti_plat_read_trig_group(tg, fwnode, CTI_DT_FILTER_OUT_SIGS);
if (!err)
- drvdata->config.trig_out_filter |= tg->used_mask;
+ bitmap_or(drvdata->config.trig_out_filter,
+ drvdata->config.trig_out_filter,
+ tg->used_mask, nr_trigs);
+ bitmap_free(tg->used_mask);
kfree(tg);
return err;
}
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 3fe2c916d228..2bbfa405cb6b 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -719,12 +719,12 @@ static ssize_t trigout_filtered_show(struct device *dev,
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *cfg = &drvdata->config;
int nr_trig_max = cfg->nr_trig_max;
- unsigned long mask = cfg->trig_out_filter;
+ unsigned long *mask = cfg->trig_out_filter;
- if (mask == 0)
+ if (bitmap_empty(mask, nr_trig_max))
return 0;
- return sysfs_emit(buf, "%*pbl\n", nr_trig_max, &mask);
+ return sysfs_emit(buf, "%*pbl\n", nr_trig_max, mask);
}
static DEVICE_ATTR_RO(trigout_filtered);
@@ -931,9 +931,9 @@ static ssize_t trigin_sig_show(struct device *dev,
struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *cfg = &drvdata->config;
- unsigned long mask = con->con_in->used_mask;
+ unsigned long *mask = con->con_in->used_mask;
- return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask);
+ return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask);
}
static ssize_t trigout_sig_show(struct device *dev,
@@ -945,9 +945,9 @@ static ssize_t trigout_sig_show(struct device *dev,
struct cti_trig_con *con = (struct cti_trig_con *)ext_attr->var;
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct cti_config *cfg = &drvdata->config;
- unsigned long mask = con->con_out->used_mask;
+ unsigned long *mask = con->con_out->used_mask;
- return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, &mask);
+ return sysfs_emit(buf, "%*pbl\n", cfg->nr_trig_max, mask);
}
/* convert a sig type id to a name */
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index c5f9e79fabc6..ef079fc18b72 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -68,7 +68,7 @@ struct fwnode_handle;
*/
struct cti_trig_grp {
int nr_sigs;
- u32 used_mask;
+ unsigned long *used_mask;
int sig_types[];
};
@@ -145,17 +145,17 @@ struct cti_config {
int enable_req_count;
/* registered triggers and filtering */
- u32 trig_in_use;
- u32 trig_out_use;
- u32 trig_out_filter;
+ unsigned long *trig_in_use;
+ unsigned long *trig_out_use;
+ unsigned long *trig_out_filter;
bool trig_filter_enable;
u8 xtrig_rchan_sel;
/* cti cross trig programmable regs */
u32 ctiappset;
u8 ctiinout_sel;
- u32 ctiinen[CTIINOUTEN_MAX];
- u32 ctiouten[CTIINOUTEN_MAX];
+ u32 *ctiinen;
+ u32 *ctiouten;
u32 ctigate;
u32 asicctl;
};
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v10 2/5] coresight: cti: use __reg_addr() helper for register access
2026-06-15 12:32 [PATCH v10 0/5] Add Qualcomm extended CTI support Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 1/5] coresight: cti: Convert trigger usage fields to dynamic Yingchao Deng
@ 2026-06-15 12:32 ` Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 3/5] coresight: cti: add Qualcomm extended CTI identification and quirks Yingchao Deng
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Yingchao Deng @ 2026-06-15 12:32 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, quic_yingdeng,
tingwei.zhang, Jinlong Mao, jie.gan, Yingchao Deng
Introduce a static inline __reg_addr(drvdata, off, index) helper in
coresight-cti.h to compute MMIO addresses from a base offset and a
per-trigger index, replacing the function-like CTIINEN(n)/CTIOUTEN(n)
macros with base offsets and explicit index arithmetic. Add reg_addr
and reg_index_addr convenience macros for zero-index and indexed
access respectively.
Convert cti_read_single_reg() and cti_write_single_reg() to static
inline wrappers in coresight-cti.h, and add indexed variants
cti_read_single_reg_index() / cti_write_single_reg_index() for
callers that need explicit bank selection. Extend cs_off_attribute
with a u32 index field and update coresight_cti_reg_show/store to
use the attribute's index field directly.
Co-developed-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
drivers/hwtracing/coresight/coresight-cti-core.c | 45 ++++++++++++++---------
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 25 +++++++------
drivers/hwtracing/coresight/coresight-cti.h | 9 +++--
drivers/hwtracing/coresight/coresight-priv.h | 4 +-
4 files changed, 50 insertions(+), 33 deletions(-)
---
drivers/hwtracing/coresight/coresight-cti-core.c | 36 +++++-------------
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 17 +++++----
drivers/hwtracing/coresight/coresight-cti.h | 46 +++++++++++++++++++++--
drivers/hwtracing/coresight/coresight-priv.h | 4 +-
4 files changed, 64 insertions(+), 39 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 572798ab504c..fa758c535ccb 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -55,16 +55,17 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
/* write the CTI trigger registers */
for (i = 0; i < config->nr_trig_max; i++) {
- writel_relaxed(config->ctiinen[i], drvdata->base + CTIINEN(i));
+ writel_relaxed(config->ctiinen[i],
+ reg_index_addr(drvdata, CTIINEN, i));
writel_relaxed(config->ctiouten[i],
- drvdata->base + CTIOUTEN(i));
+ reg_index_addr(drvdata, CTIOUTEN, i));
}
/* other regs */
- writel_relaxed(config->ctigate, drvdata->base + CTIGATE);
+ writel_relaxed(config->ctigate, reg_addr(drvdata, CTIGATE));
if (config->asicctl_impl)
- writel_relaxed(config->asicctl, drvdata->base + ASICCTL);
- writel_relaxed(config->ctiappset, drvdata->base + CTIAPPSET);
+ writel_relaxed(config->asicctl, reg_addr(drvdata, ASICCTL));
+ writel_relaxed(config->ctiappset, reg_addr(drvdata, CTIAPPSET));
/* re-enable CTI */
writel_relaxed(1, drvdata->base + CTICONTROL);
@@ -122,24 +123,6 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
return 0;
}
-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)
-{
- CS_UNLOCK(drvdata->base);
- writel_relaxed(value, drvdata->base + offset);
- CS_LOCK(drvdata->base);
-}
-
void cti_write_intack(struct device *dev, u32 ackval)
{
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
@@ -333,7 +316,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
struct cti_config *config = &drvdata->config;
u32 chan_bitmask;
u32 reg_value;
- int reg_offset;
+ u32 reg_offset;
/* ensure indexes in range */
if ((channel_idx >= config->nr_ctm_channels) ||
@@ -355,8 +338,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
/* update the local register values */
chan_bitmask = BIT(channel_idx);
- reg_offset = (direction == CTI_TRIG_IN ? CTIINEN(trigger_idx) :
- CTIOUTEN(trigger_idx));
+ reg_offset = (direction == CTI_TRIG_IN ? CTIINEN : CTIOUTEN);
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
@@ -376,7 +358,7 @@ int cti_channel_trig_op(struct device *dev, enum cti_chan_op op,
/* write through if enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, reg_offset, reg_value);
+ cti_write_single_reg_index(drvdata, reg_offset, trigger_idx, reg_value);
return 0;
}
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 2bbfa405cb6b..6165866eaefe 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -171,7 +171,7 @@ static ssize_t coresight_cti_reg_show(struct device *dev,
pm_runtime_get_sync(dev->parent);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
- val = cti_read_single_reg(drvdata, cti_attr->off);
+ val = cti_read_single_reg_index(drvdata, cti_attr->off, cti_attr->index);
pm_runtime_put_sync(dev->parent);
return sysfs_emit(buf, "0x%x\n", val);
@@ -192,7 +192,7 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
pm_runtime_get_sync(dev->parent);
scoped_guard(raw_spinlock_irqsave, &drvdata->spinlock)
- cti_write_single_reg(drvdata, cti_attr->off, val);
+ cti_write_single_reg_index(drvdata, cti_attr->off, cti_attr->index, val);
pm_runtime_put_sync(dev->parent);
return size;
@@ -202,7 +202,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
(&((struct cs_off_attribute[]) { \
{ \
__ATTR(name, 0444, coresight_cti_reg_show, NULL), \
- offset \
+ offset, \
+ 0 \
} \
})[0].attr.attr)
@@ -211,7 +212,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
{ \
__ATTR(name, 0644, coresight_cti_reg_show, \
coresight_cti_reg_store), \
- offset \
+ offset, \
+ 0 \
} \
})[0].attr.attr)
@@ -219,7 +221,8 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
(&((struct cs_off_attribute[]) { \
{ \
__ATTR(name, 0200, NULL, coresight_cti_reg_store), \
- offset \
+ offset, \
+ 0 \
} \
})[0].attr.attr)
@@ -386,7 +389,7 @@ static ssize_t inen_store(struct device *dev,
/* write through if enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, CTIINEN(index), val);
+ cti_write_single_reg_index(drvdata, CTIINEN, index, val);
return size;
}
@@ -427,7 +430,7 @@ static ssize_t outen_store(struct device *dev,
/* write through if enabled */
if (cti_is_active(config))
- cti_write_single_reg(drvdata, CTIOUTEN(index), val);
+ cti_write_single_reg_index(drvdata, CTIOUTEN, index, val);
return size;
}
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index ef079fc18b72..634bdce5cdfd 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -30,8 +30,8 @@ struct fwnode_handle;
#define CTIAPPSET 0x014
#define CTIAPPCLEAR 0x018
#define CTIAPPPULSE 0x01C
-#define CTIINEN(n) (0x020 + (4 * n))
-#define CTIOUTEN(n) (0x0A0 + (4 * n))
+#define CTIINEN 0x020
+#define CTIOUTEN 0x0A0
#define CTITRIGINSTATUS 0x130
#define CTITRIGOUTSTATUS 0x134
#define CTICHINSTATUS 0x138
@@ -217,8 +217,6 @@ int cti_enable(struct coresight_device *csdev, enum cs_mode mode,
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);
@@ -231,6 +229,46 @@ struct coresight_platform_data *
coresight_cti_get_platform_data(struct device *dev);
const char *cti_plat_get_node_name(struct fwnode_handle *fwnode);
+static inline void __iomem *__reg_addr(struct cti_drvdata *drvdata,
+ u32 off, u32 index)
+{
+ return drvdata->base + off + index * sizeof(u32);
+}
+
+#define reg_addr(drvdata, off) __reg_addr((drvdata), (off), 0)
+#define reg_index_addr(drvdata, off, i) __reg_addr((drvdata), (off), (i))
+
+static inline u32 cti_read_single_reg_index(struct cti_drvdata *drvdata,
+ u32 off, u32 index)
+{
+ u32 val;
+
+ CS_UNLOCK(drvdata->base);
+ val = readl_relaxed(reg_index_addr(drvdata, off, index));
+ CS_LOCK(drvdata->base);
+
+ return val;
+}
+
+static inline u32 cti_read_single_reg(struct cti_drvdata *drvdata, u32 off)
+{
+ return cti_read_single_reg_index(drvdata, off, 0);
+}
+
+static inline void cti_write_single_reg_index(struct cti_drvdata *drvdata,
+ u32 off, u32 index, u32 value)
+{
+ CS_UNLOCK(drvdata->base);
+ writel_relaxed(value, reg_index_addr(drvdata, off, index));
+ CS_LOCK(drvdata->base);
+}
+
+static inline void cti_write_single_reg(struct cti_drvdata *drvdata,
+ u32 off, u32 value)
+{
+ cti_write_single_reg_index(drvdata, off, 0, value);
+}
+
/* Check if a cti device is enabled */
static inline bool cti_is_active(struct cti_config *cfg)
{
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index dddac946659f..cb4736324c04 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -58,6 +58,7 @@ struct cs_pair_attribute {
struct cs_off_attribute {
struct device_attribute attr;
u32 off;
+ u32 index;
};
ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf);
@@ -67,7 +68,8 @@ ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute
(&((struct cs_off_attribute[]) { \
{ \
__ATTR(name, 0444, coresight_simple_show32, NULL), \
- offset \
+ offset, \
+ 0 \
} \
})[0].attr.attr)
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v10 3/5] coresight: cti: add Qualcomm extended CTI identification and quirks
2026-06-15 12:32 [PATCH v10 0/5] Add Qualcomm extended CTI support Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 1/5] coresight: cti: Convert trigger usage fields to dynamic Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 2/5] coresight: cti: use __reg_addr() helper for register access Yingchao Deng
@ 2026-06-15 12:32 ` Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 4/5] coresight: cti: expose banked sysfs registers for Qualcomm extended CTI Yingchao Deng
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Yingchao Deng @ 2026-06-15 12:32 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, quic_yingdeng,
tingwei.zhang, Jinlong Mao, jie.gan, Yingchao Deng
Qualcomm implements an extended variant of the ARM CoreSight CTI with a
different register layout and vendor-specific behavior. While the
programming model remains largely compatible, the register offsets differ
from the standard ARM CTI and require explicit handling.
Detect Qualcomm CTIs via the DEVARCH register and record this in the CTI
driver data. Introduce a small mapping layer to translate standard CTI
register offsets to Qualcomm-specific offsets, allowing the rest of the
driver to use a common register access path.
Additionally, handle a Qualcomm-specific quirk where the hardware does
not implement the CoreSight Claim tag protocol. Instead of clearing the
CLAIMSET register at probe time, bypass the claim/disclaim operations
entirely for Qualcomm CTIs by wrapping coresight_claim_device(),
coresight_disclaim_device_unlocked() and coresight_clear_self_claim_tag()
in thin helpers that early-return when is_qcom_cti is set.
No functional change is intended for standard ARM CTI devices.
Co-developed-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-cti-core.c | 47 +++++++++++++++--
drivers/hwtracing/coresight/coresight-cti.h | 64 +++++++++++++++++++++++-
2 files changed, 105 insertions(+), 6 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index fa758c535ccb..5b83dd4e603b 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -73,6 +73,35 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
CS_LOCK(drvdata->base);
}
+/*
+ * Qualcomm CTIs do not implement the CoreSight Claim tag protocol, so
+ * bypass coresight_clear_self_claim_tag() for them.
+ */
+static void cti_clear_self_claim_tag(struct cti_drvdata *drvdata,
+ struct csdev_access *csa)
+{
+ if (drvdata->is_qcom_cti)
+ return;
+
+ coresight_clear_self_claim_tag(csa);
+}
+
+static int cti_claim_device(struct cti_drvdata *drvdata)
+{
+ if (drvdata->is_qcom_cti)
+ return 0;
+
+ return coresight_claim_device(drvdata->csdev);
+}
+
+static void cti_unclaim_device_unlocked(struct cti_drvdata *drvdata)
+{
+ if (drvdata->is_qcom_cti)
+ return;
+
+ coresight_disclaim_device_unlocked(drvdata->csdev);
+}
+
/* write regs to hardware and enable */
static int cti_enable_hw(struct cti_drvdata *drvdata)
{
@@ -86,7 +115,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
goto cti_state_unchanged;
/* claim the device */
- rc = coresight_claim_device(drvdata->csdev);
+ rc = cti_claim_device(drvdata);
if (rc)
return rc;
@@ -101,7 +130,6 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
static int cti_disable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
- struct coresight_device *csdev = drvdata->csdev;
guard(raw_spinlock_irqsave)(&drvdata->spinlock);
@@ -118,7 +146,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
/* disable CTI */
writel_relaxed(0, drvdata->base + CTICONTROL);
- coresight_disclaim_device_unlocked(csdev);
+ cti_unclaim_device_unlocked(drvdata);
CS_LOCK(drvdata->base);
return 0;
}
@@ -144,6 +172,9 @@ void cti_write_intack(struct device *dev, u32 ackval)
/* DEVID[19:16] - number of CTM channels */
#define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19))
+/* DEVARCH[31:21] - ARCHITECT */
+#define CTI_DEVARCH_ARCHITECT(devarch_val) ((int)BMVAL(devarch_val, 21, 31))
+
static int cti_set_default_config(struct device *dev,
struct cti_drvdata *drvdata)
{
@@ -684,6 +715,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
struct coresight_desc cti_desc = { 0 };
struct coresight_platform_data *pdata = NULL;
struct resource *res = &adev->res;
+ u32 devarch;
/* driver data*/
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
@@ -708,6 +740,10 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
raw_spin_lock_init(&drvdata->spinlock);
+ devarch = readl_relaxed(drvdata->base + CORESIGHT_DEVARCH);
+ if (CTI_DEVARCH_ARCHITECT(devarch) == QCOM_ARCHITECT)
+ drvdata->is_qcom_cti = true;
+
/* initialise CTI driver config values */
ret = cti_set_default_config(dev, drvdata);
if (ret)
@@ -753,7 +789,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
cti_desc.groups = drvdata->ctidev.con_groups;
cti_desc.dev = dev;
- coresight_clear_self_claim_tag(&cti_desc.access);
+ cti_clear_self_claim_tag(drvdata, &cti_desc.access);
drvdata->csdev = coresight_register(&cti_desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
@@ -767,7 +803,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
/* all done - dec pm refcount */
pm_runtime_put(&adev->dev);
- dev_info(&drvdata->csdev->dev, "CTI initialized\n");
+ dev_info(&drvdata->csdev->dev,
+ "%sCTI initialized\n", drvdata->is_qcom_cti ? "QCOM " : "");
return 0;
}
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index 634bdce5cdfd..4b6fd6b55114 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -54,10 +54,36 @@ struct fwnode_handle;
/*
* CTI CSSoc 600 has a max of 32 trigger signals per direction.
* CTI CSSoc 400 has 8 IO triggers - other CTIs can be impl def.
+ * QCOM CTI support up to 128 trigger signals per direction.
* Max of in and out defined in the DEVID register.
* - pick up actual number used from .dts parameters if present.
*/
-#define CTIINOUTEN_MAX 32
+#define CTIINOUTEN_MAX 128
+
+/* QCOM CTI extension */
+#define QCOM_ARCHITECT 0x477
+
+#define QCOM_CTIINTACK 0x020
+#define QCOM_CTIAPPSET 0x004
+#define QCOM_CTIAPPCLEAR 0x008
+#define QCOM_CTIAPPPULSE 0x00C
+#define QCOM_CTIINEN 0x400
+#define QCOM_CTIOUTEN 0x800
+#define QCOM_CTITRIGINSTATUS 0x040
+#define QCOM_CTITRIGOUTSTATUS 0x060
+#define QCOM_CTICHINSTATUS 0x080
+#define QCOM_CTICHOUTSTATUS 0x084
+#define QCOM_CTIGATE 0x088
+#define QCOM_ASICCTL 0x08C
+/* Integration test registers */
+#define QCOM_ITCHINACK 0xE70
+#define QCOM_ITTRIGINACK 0xE80
+#define QCOM_ITCHOUT 0xE74
+#define QCOM_ITTRIGOUT 0xEA0
+#define QCOM_ITCHOUTACK 0xE78
+#define QCOM_ITTRIGOUTACK 0xEC0
+#define QCOM_ITCHIN 0xE7C
+#define QCOM_ITTRIGIN 0xEE0
/**
* Group of related trigger signals
@@ -168,6 +194,9 @@ 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.
+ * @is_qcom_cti: True if this CTI is a Qualcomm vendor-specific
+ * variant that requires register offset translation
+ * via cti_qcom_reg_off().
*/
struct cti_drvdata {
void __iomem *base;
@@ -176,6 +205,7 @@ struct cti_drvdata {
raw_spinlock_t spinlock;
struct cti_config config;
struct list_head node;
+ bool is_qcom_cti;
};
/*
@@ -229,9 +259,41 @@ struct coresight_platform_data *
coresight_cti_get_platform_data(struct device *dev);
const char *cti_plat_get_node_name(struct fwnode_handle *fwnode);
+static inline u32 cti_qcom_reg_off(u32 offset)
+{
+ switch (offset) {
+ case CTIINTACK: return QCOM_CTIINTACK;
+ case CTIAPPSET: return QCOM_CTIAPPSET;
+ case CTIAPPCLEAR: return QCOM_CTIAPPCLEAR;
+ case CTIAPPPULSE: return QCOM_CTIAPPPULSE;
+ case CTIINEN: return QCOM_CTIINEN;
+ case CTIOUTEN: return QCOM_CTIOUTEN;
+ case CTITRIGINSTATUS: return QCOM_CTITRIGINSTATUS;
+ case CTITRIGOUTSTATUS: return QCOM_CTITRIGOUTSTATUS;
+ case CTICHINSTATUS: return QCOM_CTICHINSTATUS;
+ case CTICHOUTSTATUS: return QCOM_CTICHOUTSTATUS;
+ case CTIGATE: return QCOM_CTIGATE;
+ case ASICCTL: return QCOM_ASICCTL;
+ case ITCHINACK: return QCOM_ITCHINACK;
+ case ITTRIGINACK: return QCOM_ITTRIGINACK;
+ case ITCHOUT: return QCOM_ITCHOUT;
+ case ITTRIGOUT: return QCOM_ITTRIGOUT;
+ case ITCHOUTACK: return QCOM_ITCHOUTACK;
+ case ITTRIGOUTACK: return QCOM_ITTRIGOUTACK;
+ case ITCHIN: return QCOM_ITCHIN;
+ case ITTRIGIN: return QCOM_ITTRIGIN;
+
+ default:
+ return offset;
+ }
+}
+
static inline void __iomem *__reg_addr(struct cti_drvdata *drvdata,
u32 off, u32 index)
{
+ if (unlikely(drvdata->is_qcom_cti))
+ off = cti_qcom_reg_off(off);
+
return drvdata->base + off + index * sizeof(u32);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v10 4/5] coresight: cti: expose banked sysfs registers for Qualcomm extended CTI
2026-06-15 12:32 [PATCH v10 0/5] Add Qualcomm extended CTI support Yingchao Deng
` (2 preceding siblings ...)
2026-06-15 12:32 ` [PATCH v10 3/5] coresight: cti: add Qualcomm extended CTI identification and quirks Yingchao Deng
@ 2026-06-15 12:32 ` Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 5/5] coresight: cti: document banked and missing base CTI sysfs registers Yingchao Deng
2026-06-23 9:04 ` [PATCH v10 0/5] Add Qualcomm extended CTI support Leo Yan
5 siblings, 0 replies; 8+ messages in thread
From: Yingchao Deng @ 2026-06-15 12:32 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, quic_yingdeng,
tingwei.zhang, Jinlong Mao, jie.gan, Yingchao Deng
Qualcomm extended CTI implements banked trigger status and integration
registers, where each bank covers 32 triggers. Multiple instances of
these registers are required to expose the full trigger space.
Add coresight_cti_reg_index(), coresight_cti_reg_rw_index(), and
coresight_cti_reg_wo_index() macros that carry the bank index in the
cs_off_attribute.index field, keeping the base offset and index
separate rather than encoding them together.
Add static sysfs entries for the banked CTI registers and control
their visibility based on the underlying hardware configuration.
Visibility is determined by comparing the attribute's index against
the number of banks implied by nr_trig_max (32 triggers per bank).
Registers beyond the hardware capacity are hidden, preserving the
existing ABI on standard ARM CTIs while exposing the full register
set on Qualcomm CTIs.
Reviewed-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 58 +++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-cti-sysfs.c b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
index 6165866eaefe..175f20d69232 100644
--- a/drivers/hwtracing/coresight/coresight-cti-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-cti-sysfs.c
@@ -207,6 +207,15 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
} \
})[0].attr.attr)
+#define coresight_cti_reg_index(name, offset, idx) \
+ (&((struct cs_off_attribute[]) { \
+ { \
+ __ATTR(name, 0444, coresight_cti_reg_show, NULL), \
+ offset, \
+ idx \
+ } \
+ })[0].attr.attr)
+
#define coresight_cti_reg_rw(name, offset) \
(&((struct cs_off_attribute[]) { \
{ \
@@ -217,6 +226,16 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
} \
})[0].attr.attr)
+#define coresight_cti_reg_rw_index(name, offset, idx) \
+ (&((struct cs_off_attribute[]) { \
+ { \
+ __ATTR(name, 0644, coresight_cti_reg_show, \
+ coresight_cti_reg_store), \
+ offset, \
+ idx \
+ } \
+ })[0].attr.attr)
+
#define coresight_cti_reg_wo(name, offset) \
(&((struct cs_off_attribute[]) { \
{ \
@@ -226,6 +245,15 @@ static __maybe_unused ssize_t coresight_cti_reg_store(struct device *dev,
} \
})[0].attr.attr)
+#define coresight_cti_reg_wo_index(name, offset, idx) \
+ (&((struct cs_off_attribute[]) { \
+ { \
+ __ATTR(name, 0200, NULL, coresight_cti_reg_store), \
+ offset, \
+ idx \
+ } \
+ })[0].attr.attr)
+
/* coresight management registers */
static struct attribute *coresight_cti_mgmt_attrs[] = {
coresight_cti_reg(devaff0, CTIDEVAFF0),
@@ -515,18 +543,36 @@ static struct attribute *coresight_cti_regs_attrs[] = {
&dev_attr_appclear.attr,
&dev_attr_apppulse.attr,
coresight_cti_reg(triginstatus, CTITRIGINSTATUS),
+ coresight_cti_reg_index(triginstatus1, CTITRIGINSTATUS, 1),
+ coresight_cti_reg_index(triginstatus2, CTITRIGINSTATUS, 2),
+ coresight_cti_reg_index(triginstatus3, CTITRIGINSTATUS, 3),
coresight_cti_reg(trigoutstatus, CTITRIGOUTSTATUS),
+ coresight_cti_reg_index(trigoutstatus1, CTITRIGOUTSTATUS, 1),
+ coresight_cti_reg_index(trigoutstatus2, CTITRIGOUTSTATUS, 2),
+ coresight_cti_reg_index(trigoutstatus3, CTITRIGOUTSTATUS, 3),
coresight_cti_reg(chinstatus, CTICHINSTATUS),
coresight_cti_reg(choutstatus, CTICHOUTSTATUS),
#ifdef CONFIG_CORESIGHT_CTI_INTEGRATION_REGS
coresight_cti_reg_rw(itctrl, CORESIGHT_ITCTRL),
coresight_cti_reg(ittrigin, ITTRIGIN),
+ coresight_cti_reg_index(ittrigin1, ITTRIGIN, 1),
+ coresight_cti_reg_index(ittrigin2, ITTRIGIN, 2),
+ coresight_cti_reg_index(ittrigin3, ITTRIGIN, 3),
coresight_cti_reg(itchin, ITCHIN),
coresight_cti_reg_rw(ittrigout, ITTRIGOUT),
+ coresight_cti_reg_rw_index(ittrigout1, ITTRIGOUT, 1),
+ coresight_cti_reg_rw_index(ittrigout2, ITTRIGOUT, 2),
+ coresight_cti_reg_rw_index(ittrigout3, ITTRIGOUT, 3),
coresight_cti_reg_rw(itchout, ITCHOUT),
coresight_cti_reg(itchoutack, ITCHOUTACK),
coresight_cti_reg(ittrigoutack, ITTRIGOUTACK),
+ coresight_cti_reg_index(ittrigoutack1, ITTRIGOUTACK, 1),
+ coresight_cti_reg_index(ittrigoutack2, ITTRIGOUTACK, 2),
+ coresight_cti_reg_index(ittrigoutack3, ITTRIGOUTACK, 3),
coresight_cti_reg_wo(ittriginack, ITTRIGINACK),
+ coresight_cti_reg_wo_index(ittriginack1, ITTRIGINACK, 1),
+ coresight_cti_reg_wo_index(ittriginack2, ITTRIGINACK, 2),
+ coresight_cti_reg_wo_index(ittriginack3, ITTRIGINACK, 3),
coresight_cti_reg_wo(itchinack, ITCHINACK),
#endif
NULL,
@@ -537,10 +583,22 @@ static umode_t coresight_cti_regs_is_visible(struct kobject *kobj,
{
struct device *dev = kobj_to_dev(kobj);
struct cti_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ struct device_attribute *dev_attr;
+ struct cs_off_attribute *cti_attr;
+ int max_bank;
if (attr == &dev_attr_asicctl.attr && !drvdata->config.asicctl_impl)
return 0;
+ dev_attr = container_of(attr, struct device_attribute, attr);
+ if (dev_attr->show == coresight_cti_reg_show ||
+ dev_attr->store == coresight_cti_reg_store) {
+ cti_attr = container_of(dev_attr, struct cs_off_attribute, attr);
+ max_bank = DIV_ROUND_UP(drvdata->config.nr_trig_max, 32);
+ if (cti_attr->index >= max_bank)
+ return 0;
+ }
+
return attr->mode;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v10 5/5] coresight: cti: document banked and missing base CTI sysfs registers
2026-06-15 12:32 [PATCH v10 0/5] Add Qualcomm extended CTI support Yingchao Deng
` (3 preceding siblings ...)
2026-06-15 12:32 ` [PATCH v10 4/5] coresight: cti: expose banked sysfs registers for Qualcomm extended CTI Yingchao Deng
@ 2026-06-15 12:32 ` Yingchao Deng
2026-06-23 9:04 ` [PATCH v10 0/5] Add Qualcomm extended CTI support Leo Yan
5 siblings, 0 replies; 8+ messages in thread
From: Yingchao Deng @ 2026-06-15 12:32 UTC (permalink / raw)
To: Suzuki K Poulose, Mike Leach, James Clark, Leo Yan,
Alexander Shishkin
Cc: coresight, linux-arm-kernel, linux-kernel, quic_yingdeng,
tingwei.zhang, Jinlong Mao, jie.gan, Yingchao Deng
Document the new sysfs entries triginstatus[1-3], trigoutstatus[1-3],
ittrigin[1-3], ittrigout[1-3], ittrigoutack[1-3] and ittriginack[1-3]
in the coresight-cti ABI documentation.
Also document the previously undocumented base integration test
registers itctrl, itchin, itchinack, ittrigin, ittriginack, itchout,
itchoutack, ittrigout and ittrigoutack, which were introduced in
kernel version 5.7.
Signed-off-by: Yingchao Deng <yingchao.deng@oss.qualcomm.com>
---
.../ABI/testing/sysfs-bus-coresight-devices-cti | 90 ++++++++++++++++++++++
1 file changed, 90 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
index a2aef7f5a6d7..9d7831ac455b 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
@@ -128,12 +128,102 @@ KernelVersion: 5.7
Contact: Mike Leach or Mathieu Poirier
Description: (Read) read current status of input trigger signals
+What: /sys/bus/coresight/devices/<cti-name>/regs/triginstatus[1-3]
+Date: June 2026
+KernelVersion: 7.3
+Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
+Description: (Read) read current status of QCOM extended input trigger signals.
+
What: /sys/bus/coresight/devices/<cti-name>/regs/trigoutstatus
Date: March 2020
KernelVersion: 5.7
Contact: Mike Leach or Mathieu Poirier
Description: (Read) read current status of output trigger signals.
+What: /sys/bus/coresight/devices/<cti-name>/regs/trigoutstatus[1-3]
+Date: June 2026
+KernelVersion: 7.3
+Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
+Description: (Read) read current status of QCOM extended output trigger signals.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/itctrl
+Date: March 2020
+KernelVersion: 5.7
+Contact: coresight@lists.linaro.org
+Description: (RW) Control integration mode.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/itchin
+Date: March 2020
+KernelVersion: 5.7
+Contact: coresight@lists.linaro.org
+Description: (Read) Read the values of the CTCHIN inputs.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/itchinack
+Date: March 2020
+KernelVersion: 5.7
+Contact: coresight@lists.linaro.org
+Description: (Write) Write the value of the CTCHINACK input.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/ittrigin
+Date: March 2020
+KernelVersion: 5.7
+Contact: coresight@lists.linaro.org
+Description: (Read) Read the values of the CTTRIGIN inputs.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/ittrigin[1-3]
+Date: June 2026
+KernelVersion: 7.3
+Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
+Description: (Read) Read the values of the QCOM extended CTTRIGIN inputs.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/ittriginack
+Date: March 2020
+KernelVersion: 5.7
+Contact: coresight@lists.linaro.org
+Description: (Write) Write the value of the CTTRIGINACK input.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/ittriginack[1-3]
+Date: June 2026
+KernelVersion: 7.3
+Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
+Description: (Write) Write the value of the QCOM extended CTTRIGINACK input.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/itchout
+Date: March 2020
+KernelVersion: 5.7
+Contact: coresight@lists.linaro.org
+Description: (RW) Read or write the value of the CTCHOUT outputs.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/itchoutack
+Date: March 2020
+KernelVersion: 5.7
+Contact: coresight@lists.linaro.org
+Description: (Read) Read the value of the CTCHOUTACK input.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/ittrigout
+Date: March 2020
+KernelVersion: 5.7
+Contact: coresight@lists.linaro.org
+Description: (RW) Read or write the value of the CTTRIGOUT outputs.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/ittrigout[1-3]
+Date: June 2026
+KernelVersion: 7.3
+Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
+Description: (RW) Read or write the value of the QCOM extended CTTRIGOUT outputs.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/ittrigoutack
+Date: March 2020
+KernelVersion: 5.7
+Contact: coresight@lists.linaro.org
+Description: (Read) Read the value of the CTTRIGOUTACK input.
+
+What: /sys/bus/coresight/devices/<cti-name>/regs/ittrigoutack[1-3]
+Date: June 2026
+KernelVersion: 7.3
+Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>
+Description: (Read) Read the value of the QCOM extended CTTRIGOUTACK input.
+
What: /sys/bus/coresight/devices/<cti-name>/channels/trigin_attach
Date: March 2020
KernelVersion: 5.7
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v10 0/5] Add Qualcomm extended CTI support
2026-06-15 12:32 [PATCH v10 0/5] Add Qualcomm extended CTI support Yingchao Deng
` (4 preceding siblings ...)
2026-06-15 12:32 ` [PATCH v10 5/5] coresight: cti: document banked and missing base CTI sysfs registers Yingchao Deng
@ 2026-06-23 9:04 ` Leo Yan
2026-06-23 9:52 ` Yingchao Deng (Consultant)
5 siblings, 1 reply; 8+ messages in thread
From: Leo Yan @ 2026-06-23 9:04 UTC (permalink / raw)
To: Yingchao Deng
Cc: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
coresight, linux-arm-kernel, linux-kernel, quic_yingdeng,
tingwei.zhang, Jinlong Mao, jie.gan
On Mon, Jun 15, 2026 at 08:32:28PM +0800, Yingchao Deng wrote:
> The Qualcomm extended CTI is a heavily parameterized version of ARM’s
> CSCTI. It allows a debugger to send to trigger events to a processor or to
> send a trigger event to one or more processors when a trigger event occurs
> on another processor on the same SoC, or even between SoCs.
>
> Qualcomm extended CTI supports up to 128 triggers. And some of the register
> offsets are changed.
>
> The commands to configure CTI triggers are the same as ARM's CTI.
This series looks good to me and I tested:
- Confirmed no any change for standard CTI;
- Perf command;
- Build bisection.
Tested-by: Leo Yan <leo.yan@arm.com>
Mike may also want to take a look in case there is any overlap with his
claim tags init patch [1]. I don't have a strong preference on which
series goes in first, as the claim tag handling in this series looks
clean enough to me.
@Yingchao, just a small suggestion: rc1–rc4 is usually the best window
for getting patches merged. If you receive comments and are able to
address them quickly, it may be worth respin patches during that
period to try catching the next merge window. This is no guarantees,
just thought it might be useful to share as a general tip :)
[1] https://lore.kernel.org/linux-arm-kernel/20260619160148.499223-2-mike.leach@arm.com/
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v10 0/5] Add Qualcomm extended CTI support
2026-06-23 9:04 ` [PATCH v10 0/5] Add Qualcomm extended CTI support Leo Yan
@ 2026-06-23 9:52 ` Yingchao Deng (Consultant)
0 siblings, 0 replies; 8+ messages in thread
From: Yingchao Deng (Consultant) @ 2026-06-23 9:52 UTC (permalink / raw)
To: Leo Yan, Yingchao Deng
Cc: Suzuki K Poulose, Mike Leach, James Clark, Alexander Shishkin,
coresight, linux-arm-kernel, linux-kernel, tingwei.zhang,
Jinlong Mao, jie.gan, Yingchao Deng
On 6/23/2026 5:04 PM, Leo Yan wrote:
> This series looks good to me and I tested:
>
> - Confirmed no any change for standard CTI;
> - Perf command;
> - Build bisection.
>
> Tested-by: Leo Yan<leo.yan@arm.com>
>
> Mike may also want to take a look in case there is any overlap with his
> claim tags init patch [1]. I don't have a strong preference on which
> series goes in first, as the claim tag handling in this series looks
> clean enough to me.
>
> @Yingchao, just a small suggestion: rc1–rc4 is usually the best window
> for getting patches merged. If you receive comments and are able to
> address them quickly, it may be worth respin patches during that
> period to try catching the next merge window. This is no guarantees,
> just thought it might be useful to share as a general tip 🙂
Thanks Leo for testing and the helpful suggestion.
Thanks,
Yingchao
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-06-23 9:53 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-15 12:32 [PATCH v10 0/5] Add Qualcomm extended CTI support Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 1/5] coresight: cti: Convert trigger usage fields to dynamic Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 2/5] coresight: cti: use __reg_addr() helper for register access Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 3/5] coresight: cti: add Qualcomm extended CTI identification and quirks Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 4/5] coresight: cti: expose banked sysfs registers for Qualcomm extended CTI Yingchao Deng
2026-06-15 12:32 ` [PATCH v10 5/5] coresight: cti: document banked and missing base CTI sysfs registers Yingchao Deng
2026-06-23 9:04 ` [PATCH v10 0/5] Add Qualcomm extended CTI support Leo Yan
2026-06-23 9:52 ` Yingchao Deng (Consultant)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox