coresight-tpdm: Add timestamp control register support for the CMB
CMB_TIER register is CMB subunit timestamp insertion enable register. Bit 0 is PATT_TSENAB bit. Set this bit to 1 to request a timestamp following a CMB interface pattern match. Bit 1 is XTRIG_TSENAB bit. Set this bit to 1 to request a timestamp following a CMB CTI timestamp request. Bit 2 is TS_ALL bit. Set this bit to 1 to request timestamp for all packets. Reviewed-by: James Clark <james.clark@arm.com> Signed-off-by: Tao Zhang <quic_taozha@quicinc.com> Signed-off-by: Jinlong Mao <quic_jinlmao@quicinc.com> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Link: https://lore.kernel.org/r/1707024641-22460-9-git-send-email-quic_taozha@quicinc.com
This commit is contained in:
parent
53d4a017a5
commit
dc6ce57e2a
@ -214,3 +214,38 @@ KernelVersion 6.9
|
|||||||
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||||
Description:
|
Description:
|
||||||
(RW) Set/Get the mask of the pattern for the CMB subunit TPDM.
|
(RW) Set/Get the mask of the pattern for the CMB subunit TPDM.
|
||||||
|
|
||||||
|
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_patt/enable_ts
|
||||||
|
Date: January 2024
|
||||||
|
KernelVersion 6.9
|
||||||
|
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||||
|
Description:
|
||||||
|
(Write) Set the pattern timestamp of CMB tpdm. Read
|
||||||
|
the pattern timestamp of CMB tpdm.
|
||||||
|
|
||||||
|
Accepts only one of the 2 values - 0 or 1.
|
||||||
|
0 : Disable CMB pattern timestamp.
|
||||||
|
1 : Enable CMB pattern timestamp.
|
||||||
|
|
||||||
|
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_ts
|
||||||
|
Date: January 2024
|
||||||
|
KernelVersion 6.9
|
||||||
|
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||||
|
Description:
|
||||||
|
(RW) Set/Get the trigger timestamp of the CMB for tpdm.
|
||||||
|
|
||||||
|
Accepts only one of the 2 values - 0 or 1.
|
||||||
|
0 : Set the CMB trigger type to false
|
||||||
|
1 : Set the CMB trigger type to true
|
||||||
|
|
||||||
|
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_ts_all
|
||||||
|
Date: January 2024
|
||||||
|
KernelVersion 6.9
|
||||||
|
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
|
||||||
|
Description:
|
||||||
|
(RW) Read or write the status of timestamp upon all interface.
|
||||||
|
Only value 0 and 1 can be written to this node. Set this node to 1 to requeset
|
||||||
|
timestamp to all trace packet.
|
||||||
|
Accepts only one of the 2 values - 0 or 1.
|
||||||
|
0 : Disable the timestamp of all trace packets.
|
||||||
|
1 : Enable the timestamp of all trace packets.
|
||||||
|
@ -322,6 +322,31 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
|
|||||||
writel_relaxed(val, drvdata->base + TPDM_DSB_CR);
|
writel_relaxed(val, drvdata->base + TPDM_DSB_CR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_cmb_tier(struct tpdm_drvdata *drvdata)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = readl_relaxed(drvdata->base + TPDM_CMB_TIER);
|
||||||
|
|
||||||
|
/* Clear all relevant fields */
|
||||||
|
val &= ~(TPDM_CMB_TIER_PATT_TSENAB | TPDM_CMB_TIER_TS_ALL |
|
||||||
|
TPDM_CMB_TIER_XTRIG_TSENAB);
|
||||||
|
|
||||||
|
/* Set pattern timestamp type and enablement */
|
||||||
|
if (drvdata->cmb->patt_ts)
|
||||||
|
val |= TPDM_CMB_TIER_PATT_TSENAB;
|
||||||
|
|
||||||
|
/* Set trigger timestamp */
|
||||||
|
if (drvdata->cmb->trig_ts)
|
||||||
|
val |= TPDM_CMB_TIER_XTRIG_TSENAB;
|
||||||
|
|
||||||
|
/* Set all timestamp enablement*/
|
||||||
|
if (drvdata->cmb->ts_all)
|
||||||
|
val |= TPDM_CMB_TIER_TS_ALL;
|
||||||
|
|
||||||
|
writel_relaxed(val, drvdata->base + TPDM_CMB_TIER);
|
||||||
|
}
|
||||||
|
|
||||||
static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
|
static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
|
||||||
{
|
{
|
||||||
u32 val, i;
|
u32 val, i;
|
||||||
@ -341,6 +366,8 @@ static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
|
|||||||
drvdata->base + TPDM_CMB_XPMR(i));
|
drvdata->base + TPDM_CMB_XPMR(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_cmb_tier(drvdata);
|
||||||
|
|
||||||
val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
|
val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
|
||||||
/*
|
/*
|
||||||
* Set to 0 for continuous CMB collection mode,
|
* Set to 0 for continuous CMB collection mode,
|
||||||
@ -687,9 +714,18 @@ static ssize_t enable_ts_show(struct device *dev,
|
|||||||
char *buf)
|
char *buf)
|
||||||
{
|
{
|
||||||
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||||
|
struct tpdm_dataset_attribute *tpdm_attr =
|
||||||
|
container_of(attr, struct tpdm_dataset_attribute, attr);
|
||||||
|
ssize_t size = -EINVAL;
|
||||||
|
|
||||||
return sysfs_emit(buf, "%u\n",
|
if (tpdm_attr->mem == DSB_PATT)
|
||||||
(unsigned int)drvdata->dsb->patt_ts);
|
size = sysfs_emit(buf, "%u\n",
|
||||||
|
(unsigned int)drvdata->dsb->patt_ts);
|
||||||
|
else if (tpdm_attr->mem == CMB_PATT)
|
||||||
|
size = sysfs_emit(buf, "%u\n",
|
||||||
|
(unsigned int)drvdata->cmb->patt_ts);
|
||||||
|
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -701,17 +737,23 @@ static ssize_t enable_ts_store(struct device *dev,
|
|||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||||
|
struct tpdm_dataset_attribute *tpdm_attr =
|
||||||
|
container_of(attr, struct tpdm_dataset_attribute, attr);
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
|
|
||||||
if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
|
if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock(&drvdata->spinlock);
|
guard(spinlock)(&drvdata->spinlock);
|
||||||
drvdata->dsb->patt_ts = !!val;
|
if (tpdm_attr->mem == DSB_PATT)
|
||||||
spin_unlock(&drvdata->spinlock);
|
drvdata->dsb->patt_ts = !!val;
|
||||||
|
else if (tpdm_attr->mem == CMB_PATT)
|
||||||
|
drvdata->cmb->patt_ts = !!val;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RW(enable_ts);
|
|
||||||
|
|
||||||
static ssize_t set_type_show(struct device *dev,
|
static ssize_t set_type_show(struct device *dev,
|
||||||
struct device_attribute *attr,
|
struct device_attribute *attr,
|
||||||
@ -842,6 +884,68 @@ static ssize_t cmb_mode_store(struct device *dev,
|
|||||||
}
|
}
|
||||||
static DEVICE_ATTR_RW(cmb_mode);
|
static DEVICE_ATTR_RW(cmb_mode);
|
||||||
|
|
||||||
|
static ssize_t cmb_ts_all_show(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||||
|
|
||||||
|
return sysfs_emit(buf, "%u\n",
|
||||||
|
(unsigned int)drvdata->cmb->ts_all);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cmb_ts_all_store(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||||
|
unsigned long val;
|
||||||
|
|
||||||
|
if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
guard(spinlock)(&drvdata->spinlock);
|
||||||
|
if (val)
|
||||||
|
drvdata->cmb->ts_all = true;
|
||||||
|
else
|
||||||
|
drvdata->cmb->ts_all = false;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR_RW(cmb_ts_all);
|
||||||
|
|
||||||
|
static ssize_t cmb_trig_ts_show(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||||
|
|
||||||
|
return sysfs_emit(buf, "%u\n",
|
||||||
|
(unsigned int)drvdata->cmb->trig_ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t cmb_trig_ts_store(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||||
|
unsigned long val;
|
||||||
|
|
||||||
|
if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
guard(spinlock)(&drvdata->spinlock);
|
||||||
|
if (val)
|
||||||
|
drvdata->cmb->trig_ts = true;
|
||||||
|
else
|
||||||
|
drvdata->cmb->trig_ts = false;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR_RW(cmb_trig_ts);
|
||||||
|
|
||||||
static struct attribute *tpdm_dsb_edge_attrs[] = {
|
static struct attribute *tpdm_dsb_edge_attrs[] = {
|
||||||
&dev_attr_ctrl_idx.attr,
|
&dev_attr_ctrl_idx.attr,
|
||||||
&dev_attr_ctrl_val.attr,
|
&dev_attr_ctrl_val.attr,
|
||||||
@ -910,7 +1014,7 @@ static struct attribute *tpdm_dsb_patt_attrs[] = {
|
|||||||
DSB_PATT_MASK_ATTR(5),
|
DSB_PATT_MASK_ATTR(5),
|
||||||
DSB_PATT_MASK_ATTR(6),
|
DSB_PATT_MASK_ATTR(6),
|
||||||
DSB_PATT_MASK_ATTR(7),
|
DSB_PATT_MASK_ATTR(7),
|
||||||
&dev_attr_enable_ts.attr,
|
DSB_PATT_ENABLE_TS,
|
||||||
&dev_attr_set_type.attr,
|
&dev_attr_set_type.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
@ -964,6 +1068,7 @@ static struct attribute *tpdm_cmb_patt_attrs[] = {
|
|||||||
CMB_PATT_ATTR(1),
|
CMB_PATT_ATTR(1),
|
||||||
CMB_PATT_MASK_ATTR(0),
|
CMB_PATT_MASK_ATTR(0),
|
||||||
CMB_PATT_MASK_ATTR(1),
|
CMB_PATT_MASK_ATTR(1),
|
||||||
|
CMB_PATT_ENABLE_TS,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -976,6 +1081,8 @@ static struct attribute *tpdm_dsb_attrs[] = {
|
|||||||
|
|
||||||
static struct attribute *tpdm_cmb_attrs[] = {
|
static struct attribute *tpdm_cmb_attrs[] = {
|
||||||
&dev_attr_cmb_mode.attr,
|
&dev_attr_cmb_mode.attr,
|
||||||
|
&dev_attr_cmb_ts_all.attr,
|
||||||
|
&dev_attr_cmb_trig_ts.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
/* CMB Subunit Registers */
|
/* CMB Subunit Registers */
|
||||||
#define TPDM_CMB_CR (0xA00)
|
#define TPDM_CMB_CR (0xA00)
|
||||||
|
/* CMB subunit timestamp insertion enable register */
|
||||||
|
#define TPDM_CMB_TIER (0xA04)
|
||||||
/* CMB subunit timestamp pattern registers */
|
/* CMB subunit timestamp pattern registers */
|
||||||
#define TPDM_CMB_TPR(n) (0xA08 + (n * 4))
|
#define TPDM_CMB_TPR(n) (0xA08 + (n * 4))
|
||||||
/* CMB subunit timestamp pattern mask registers */
|
/* CMB subunit timestamp pattern mask registers */
|
||||||
@ -24,6 +26,12 @@
|
|||||||
#define TPDM_CMB_CR_ENA BIT(0)
|
#define TPDM_CMB_CR_ENA BIT(0)
|
||||||
/* Trace collection mode for CMB subunit */
|
/* Trace collection mode for CMB subunit */
|
||||||
#define TPDM_CMB_CR_MODE BIT(1)
|
#define TPDM_CMB_CR_MODE BIT(1)
|
||||||
|
/* Timestamp control for pattern match */
|
||||||
|
#define TPDM_CMB_TIER_PATT_TSENAB BIT(0)
|
||||||
|
/* CMB CTI timestamp request */
|
||||||
|
#define TPDM_CMB_TIER_XTRIG_TSENAB BIT(1)
|
||||||
|
/* For timestamp fo all trace */
|
||||||
|
#define TPDM_CMB_TIER_TS_ALL BIT(2)
|
||||||
|
|
||||||
/* Patten register number */
|
/* Patten register number */
|
||||||
#define TPDM_CMB_MAX_PATT 2
|
#define TPDM_CMB_MAX_PATT 2
|
||||||
@ -134,6 +142,15 @@
|
|||||||
} \
|
} \
|
||||||
})[0].attr.attr)
|
})[0].attr.attr)
|
||||||
|
|
||||||
|
#define tpdm_patt_enable_ts(name, mem) \
|
||||||
|
(&((struct tpdm_dataset_attribute[]) { \
|
||||||
|
{ \
|
||||||
|
__ATTR(name, 0644, enable_ts_show, \
|
||||||
|
enable_ts_store), \
|
||||||
|
mem, \
|
||||||
|
} \
|
||||||
|
})[0].attr.attr)
|
||||||
|
|
||||||
#define DSB_EDGE_CTRL_ATTR(nr) \
|
#define DSB_EDGE_CTRL_ATTR(nr) \
|
||||||
tpdm_simple_dataset_ro(edcr##nr, \
|
tpdm_simple_dataset_ro(edcr##nr, \
|
||||||
DSB_EDGE_CTRL, nr)
|
DSB_EDGE_CTRL, nr)
|
||||||
@ -158,6 +175,10 @@
|
|||||||
tpdm_simple_dataset_rw(tpmr##nr, \
|
tpdm_simple_dataset_rw(tpmr##nr, \
|
||||||
DSB_PATT_MASK, nr)
|
DSB_PATT_MASK, nr)
|
||||||
|
|
||||||
|
#define DSB_PATT_ENABLE_TS \
|
||||||
|
tpdm_patt_enable_ts(enable_ts, \
|
||||||
|
DSB_PATT)
|
||||||
|
|
||||||
#define DSB_MSR_ATTR(nr) \
|
#define DSB_MSR_ATTR(nr) \
|
||||||
tpdm_simple_dataset_rw(msr##nr, \
|
tpdm_simple_dataset_rw(msr##nr, \
|
||||||
DSB_MSR, nr)
|
DSB_MSR, nr)
|
||||||
@ -178,6 +199,10 @@
|
|||||||
tpdm_simple_dataset_rw(tpmr##nr, \
|
tpdm_simple_dataset_rw(tpmr##nr, \
|
||||||
CMB_PATT_MASK, nr)
|
CMB_PATT_MASK, nr)
|
||||||
|
|
||||||
|
#define CMB_PATT_ENABLE_TS \
|
||||||
|
tpdm_patt_enable_ts(enable_ts, \
|
||||||
|
CMB_PATT)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct dsb_dataset - specifics associated to dsb dataset
|
* struct dsb_dataset - specifics associated to dsb dataset
|
||||||
* @mode: DSB programming mode
|
* @mode: DSB programming mode
|
||||||
@ -217,6 +242,9 @@ struct dsb_dataset {
|
|||||||
* @patt_mask: Save value for pattern mask
|
* @patt_mask: Save value for pattern mask
|
||||||
* @trig_patt: Save value for trigger pattern
|
* @trig_patt: Save value for trigger pattern
|
||||||
* @trig_patt_mask: Save value for trigger pattern mask
|
* @trig_patt_mask: Save value for trigger pattern mask
|
||||||
|
* @patt_ts: Indicates if pattern match for timestamp is enabled.
|
||||||
|
* @trig_ts: Indicates if CTI trigger for timestamp is enabled.
|
||||||
|
* @ts_all: Indicates if timestamp is enabled for all packets.
|
||||||
*/
|
*/
|
||||||
struct cmb_dataset {
|
struct cmb_dataset {
|
||||||
u32 trace_mode;
|
u32 trace_mode;
|
||||||
@ -224,6 +252,9 @@ struct cmb_dataset {
|
|||||||
u32 patt_mask[TPDM_CMB_MAX_PATT];
|
u32 patt_mask[TPDM_CMB_MAX_PATT];
|
||||||
u32 trig_patt[TPDM_CMB_MAX_PATT];
|
u32 trig_patt[TPDM_CMB_MAX_PATT];
|
||||||
u32 trig_patt_mask[TPDM_CMB_MAX_PATT];
|
u32 trig_patt_mask[TPDM_CMB_MAX_PATT];
|
||||||
|
bool patt_ts;
|
||||||
|
bool trig_ts;
|
||||||
|
bool ts_all;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user