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

coresight-tpdm: Add nodes to configure pattern match output



Add nodes to configure trigger pattern and trigger pattern mask.
Each DSB subunit TPDM has maximum of n(n<7) XPR registers to
configure trigger pattern match output. Eight 32 bit registers
providing DSB interface trigger output pattern match comparison.
And each DSB subunit TPDM has maximum of m(m<7) XPMR registers to
configure trigger pattern mask match output. Eight 32 bit
registers providing DSB interface trigger output pattern match
mask.

Signed-off-by: default avatarTao Zhang <quic_taozha@quicinc.com>
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/1695882586-10306-11-git-send-email-quic_taozha@quicinc.com
parent f376caf2
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -108,3 +108,19 @@ KernelVersion 6.7
Contact:	Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Description:
		Read a set of the edge control mask of the DSB in TPDM.

What:		/sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpr[0:7]
Date:		March 2023
KernelVersion	6.7
Contact:	Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Description:
		(RW) Set/Get the value of the trigger pattern for the DSB
		subunit TPDM.

What:		/sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpmr[0:7]
Date:		March 2023
KernelVersion	6.7
Contact:	Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Description:
		(RW) Set/Get the mask of the trigger pattern for the DSB
		subunit TPDM.
 No newline at end of file
+81 −1
Original line number Diff line number Diff line
@@ -41,10 +41,58 @@ static ssize_t tpdm_simple_dataset_show(struct device *dev,
			return -EINVAL;
		return sysfs_emit(buf, "0x%x\n",
			drvdata->dsb->edge_ctrl_mask[tpdm_attr->idx]);
	case DSB_TRIG_PATT:
		if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT)
			return -EINVAL;
		return sysfs_emit(buf, "0x%x\n",
			drvdata->dsb->trig_patt[tpdm_attr->idx]);
	case DSB_TRIG_PATT_MASK:
		if (tpdm_attr->idx >= TPDM_DSB_MAX_PATT)
			return -EINVAL;
		return sysfs_emit(buf, "0x%x\n",
			drvdata->dsb->trig_patt_mask[tpdm_attr->idx]);
	}
	return -EINVAL;
}

/* Write dataset array member with the index number */
static ssize_t tpdm_simple_dataset_store(struct device *dev,
					 struct device_attribute *attr,
					 const char *buf,
					 size_t size)
{
	unsigned long val;
	ssize_t ret = size;

	struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
	struct tpdm_dataset_attribute *tpdm_attr =
		container_of(attr, struct tpdm_dataset_attribute, attr);

	if (kstrtoul(buf, 0, &val))
		return -EINVAL;

	spin_lock(&drvdata->spinlock);
	switch (tpdm_attr->mem) {
	case DSB_TRIG_PATT:
		if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)
			drvdata->dsb->trig_patt[tpdm_attr->idx] = val;
		else
			ret = -EINVAL;
		break;
	case DSB_TRIG_PATT_MASK:
		if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)
			drvdata->dsb->trig_patt_mask[tpdm_attr->idx] = val;
		else
			ret = -EINVAL;
		break;
	default:
		ret = -EINVAL;
	}
	spin_unlock(&drvdata->spinlock);

	return ret;
}

static bool tpdm_has_dsb_dataset(struct tpdm_drvdata *drvdata)
{
	return (drvdata->datasets & TPDM_PIDR0_DS_DSB);
@@ -103,7 +151,12 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata)
	for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
		writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
			   drvdata->base + TPDM_DSB_EDCMR(i));

	for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
		writel_relaxed(drvdata->dsb->trig_patt[i],
			   drvdata->base + TPDM_DSB_XPR(i));
		writel_relaxed(drvdata->dsb->trig_patt_mask[i],
			   drvdata->base + TPDM_DSB_XPMR(i));
	}
	val = readl_relaxed(drvdata->base + TPDM_DSB_TIER);
	/* Set trigger timestamp */
	if (drvdata->dsb->trig_ts)
@@ -532,6 +585,26 @@ static struct attribute *tpdm_dsb_edge_attrs[] = {
	NULL,
};

static struct attribute *tpdm_dsb_trig_patt_attrs[] = {
	DSB_TRIG_PATT_ATTR(0),
	DSB_TRIG_PATT_ATTR(1),
	DSB_TRIG_PATT_ATTR(2),
	DSB_TRIG_PATT_ATTR(3),
	DSB_TRIG_PATT_ATTR(4),
	DSB_TRIG_PATT_ATTR(5),
	DSB_TRIG_PATT_ATTR(6),
	DSB_TRIG_PATT_ATTR(7),
	DSB_TRIG_PATT_MASK_ATTR(0),
	DSB_TRIG_PATT_MASK_ATTR(1),
	DSB_TRIG_PATT_MASK_ATTR(2),
	DSB_TRIG_PATT_MASK_ATTR(3),
	DSB_TRIG_PATT_MASK_ATTR(4),
	DSB_TRIG_PATT_MASK_ATTR(5),
	DSB_TRIG_PATT_MASK_ATTR(6),
	DSB_TRIG_PATT_MASK_ATTR(7),
	NULL,
};

static struct attribute *tpdm_dsb_attrs[] = {
	&dev_attr_dsb_mode.attr,
	&dev_attr_dsb_trig_ts.attr,
@@ -550,10 +623,17 @@ static struct attribute_group tpdm_dsb_edge_grp = {
	.name = "dsb_edge",
};

static struct attribute_group tpdm_dsb_trig_patt_grp = {
	.attrs = tpdm_dsb_trig_patt_attrs,
	.is_visible = tpdm_dsb_is_visible,
	.name = "dsb_trig_patt",
};

static const struct attribute_group *tpdm_attr_grps[] = {
	&tpdm_attr_grp,
	&tpdm_dsb_attr_grp,
	&tpdm_dsb_edge_grp,
	&tpdm_dsb_trig_patt_grp,
	NULL,
};

+28 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@
/* DSB Subunit Registers */
#define TPDM_DSB_CR		(0x780)
#define TPDM_DSB_TIER		(0x784)
#define TPDM_DSB_XPR(n)		(0x7C8 + (n * 4))
#define TPDM_DSB_XPMR(n)	(0x7E8 + (n * 4))
#define TPDM_DSB_EDCR(n)	(0x808 + (n * 4))
#define TPDM_DSB_EDCMR(n)	(0x848 + (n * 4))

@@ -80,6 +82,8 @@
#define TPDM_DSB_MAX_EDCR	16
/* MAX number of EDCMR registers */
#define TPDM_DSB_MAX_EDCMR	8
/* MAX number of DSB pattern */
#define TPDM_DSB_MAX_PATT	8

#define tpdm_simple_dataset_ro(name, mem, idx)			\
	(&((struct tpdm_dataset_attribute[]) {			\
@@ -90,6 +94,16 @@
	   }								\
	})[0].attr.attr)

#define tpdm_simple_dataset_rw(name, mem, idx)			\
	(&((struct tpdm_dataset_attribute[]) {			\
	   {								\
		__ATTR(name, 0644, tpdm_simple_dataset_show,		\
		tpdm_simple_dataset_store),		\
		mem,							\
		idx,							\
	   }								\
	})[0].attr.attr)

#define DSB_EDGE_CTRL_ATTR(nr)					\
		tpdm_simple_dataset_ro(edcr##nr,		\
		DSB_EDGE_CTRL, nr)
@@ -98,12 +112,22 @@
		tpdm_simple_dataset_ro(edcmr##nr,		\
		DSB_EDGE_CTRL_MASK, nr)

#define DSB_TRIG_PATT_ATTR(nr)					\
		tpdm_simple_dataset_rw(xpr##nr,			\
		DSB_TRIG_PATT, nr)

#define DSB_TRIG_PATT_MASK_ATTR(nr)				\
		tpdm_simple_dataset_rw(xpmr##nr,		\
		DSB_TRIG_PATT_MASK, nr)

/**
 * struct dsb_dataset - specifics associated to dsb dataset
 * @mode:             DSB programming mode
 * @edge_ctrl_idx     Index number of the edge control
 * @edge_ctrl:        Save value for edge control
 * @edge_ctrl_mask:   Save value for edge control mask
 * @trig_patt:        Save value for trigger pattern
 * @trig_patt_mask:   Save value for trigger pattern mask
 * @trig_ts:          Enable/Disable trigger timestamp.
 * @trig_type:        Enable/Disable trigger type.
 */
@@ -112,6 +136,8 @@ struct dsb_dataset {
	u32			edge_ctrl_idx;
	u32			edge_ctrl[TPDM_DSB_MAX_EDCR];
	u32			edge_ctrl_mask[TPDM_DSB_MAX_EDCMR];
	u32			trig_patt[TPDM_DSB_MAX_PATT];
	u32			trig_patt_mask[TPDM_DSB_MAX_PATT];
	bool			trig_ts;
	bool			trig_type;
};
@@ -141,6 +167,8 @@ struct tpdm_drvdata {
enum dataset_mem {
	DSB_EDGE_CTRL,
	DSB_EDGE_CTRL_MASK,
	DSB_TRIG_PATT,
	DSB_TRIG_PATT_MASK,
};

/**