Commit dc6ce57e authored by Tao Zhang's avatar Tao Zhang Committed by Suzuki K Poulose
Browse files

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: default avatarJames Clark <james.clark@arm.com>
Signed-off-by: default avatarTao Zhang <quic_taozha@quicinc.com>
Signed-off-by: default avatarJinlong Mao <quic_jinlmao@quicinc.com>
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/1707024641-22460-9-git-send-email-quic_taozha@quicinc.com
parent 53d4a017
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -214,3 +214,38 @@ KernelVersion 6.9
Contact:	Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Description:
		(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.
+114 −7
Original line number Diff line number Diff line
@@ -322,6 +322,31 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
	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)
{
	u32 val, i;
@@ -341,6 +366,8 @@ static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
			drvdata->base + TPDM_CMB_XPMR(i));
	}

	set_cmb_tier(drvdata);

	val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
	/*
	 * Set to 0 for continuous CMB collection mode,
@@ -687,9 +714,18 @@ static ssize_t enable_ts_show(struct device *dev,
			      char *buf)
{
	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)
		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)
{
	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;

	if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
		return -EINVAL;

	spin_lock(&drvdata->spinlock);
	guard(spinlock)(&drvdata->spinlock);
	if (tpdm_attr->mem == DSB_PATT)
		drvdata->dsb->patt_ts = !!val;
	spin_unlock(&drvdata->spinlock);
	else if (tpdm_attr->mem == CMB_PATT)
		drvdata->cmb->patt_ts = !!val;
	else
		return -EINVAL;

	return size;
}
static DEVICE_ATTR_RW(enable_ts);

static ssize_t set_type_show(struct device *dev,
			     struct device_attribute *attr,
@@ -842,6 +884,68 @@ static ssize_t cmb_mode_store(struct device *dev,
}
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[] = {
	&dev_attr_ctrl_idx.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(6),
	DSB_PATT_MASK_ATTR(7),
	&dev_attr_enable_ts.attr,
	DSB_PATT_ENABLE_TS,
	&dev_attr_set_type.attr,
	NULL,
};
@@ -964,6 +1068,7 @@ static struct attribute *tpdm_cmb_patt_attrs[] = {
	CMB_PATT_ATTR(1),
	CMB_PATT_MASK_ATTR(0),
	CMB_PATT_MASK_ATTR(1),
	CMB_PATT_ENABLE_TS,
	NULL,
};

@@ -976,6 +1081,8 @@ static struct attribute *tpdm_dsb_attrs[] = {

static struct attribute *tpdm_cmb_attrs[] = {
	&dev_attr_cmb_mode.attr,
	&dev_attr_cmb_ts_all.attr,
	&dev_attr_cmb_trig_ts.attr,
	NULL,
};

+31 −0
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@

/* CMB Subunit Registers */
#define TPDM_CMB_CR		(0xA00)
/* CMB subunit timestamp insertion enable register */
#define TPDM_CMB_TIER		(0xA04)
/* CMB subunit timestamp pattern registers */
#define TPDM_CMB_TPR(n)		(0xA08 + (n * 4))
/* CMB subunit timestamp pattern mask registers */
@@ -24,6 +26,12 @@
#define TPDM_CMB_CR_ENA		BIT(0)
/* Trace collection mode for CMB subunit */
#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 */
#define TPDM_CMB_MAX_PATT		2
@@ -134,6 +142,15 @@
	   }								\
	})[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)					\
		tpdm_simple_dataset_ro(edcr##nr,		\
		DSB_EDGE_CTRL, nr)
@@ -158,6 +175,10 @@
		tpdm_simple_dataset_rw(tpmr##nr,		\
		DSB_PATT_MASK, nr)

#define DSB_PATT_ENABLE_TS					\
		tpdm_patt_enable_ts(enable_ts,			\
		DSB_PATT)

#define DSB_MSR_ATTR(nr)					\
		tpdm_simple_dataset_rw(msr##nr,			\
		DSB_MSR, nr)
@@ -178,6 +199,10 @@
		tpdm_simple_dataset_rw(tpmr##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
 * @mode:             DSB programming mode
@@ -217,6 +242,9 @@ struct dsb_dataset {
 * @patt_mask:        Save value for pattern mask
 * @trig_patt:        Save value for trigger pattern
 * @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 {
	u32			trace_mode;
@@ -224,6 +252,9 @@ struct cmb_dataset {
	u32			patt_mask[TPDM_CMB_MAX_PATT];
	u32			trig_patt[TPDM_CMB_MAX_PATT];
	u32			trig_patt_mask[TPDM_CMB_MAX_PATT];
	bool			patt_ts;
	bool			trig_ts;
	bool			ts_all;
};

/**