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

coresight-tpdm: Add support to configure CMB



TPDM CMB subunits support two forms of CMB data set element creation:
continuous and trace-on-change collection mode. Continuous change
creates CMB data set elements on every CMBCLK edge. Trace-on-change
creates CMB data set elements only when a new data set element differs
in value from the previous element in a CMB data set. Set CMB_CR.MODE
to 0 for continuous CMB collection mode. Set CMB_CR.MODE to 1 for
trace-on-change CMB collection mode.

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-7-git-send-email-quic_taozha@quicinc.com
parent e6d7f525
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -170,3 +170,17 @@ Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_t
Description:
		(RW) Set/Get the MSR(mux select register) for the DSB subunit
		TPDM.

What:		/sys/bus/coresight/devices/<tpdm-name>/cmb_mode
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 data collection mode of CMB tpdm. Continuous
		change creates CMB data set elements on every CMBCLK edge.
		Trace-on-change creates CMB data set elements only when a new
		data set element differs in value from the previous element
		in a CMB data set.

		Accepts only one of the 2 values -  0 or 1.
		0 : Continuous CMB collection mode.
		1 : Trace-on-change CMB collection mode.
+60 −0
Original line number Diff line number Diff line
@@ -137,6 +137,18 @@ static umode_t tpdm_dsb_is_visible(struct kobject *kobj,
	return 0;
}

static umode_t tpdm_cmb_is_visible(struct kobject *kobj,
				   struct attribute *attr, int n)
{
	struct device *dev = kobj_to_dev(kobj);
	struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);

	if (drvdata && tpdm_has_cmb_dataset(drvdata))
		return attr->mode;

	return 0;
}

static umode_t tpdm_dsb_msr_is_visible(struct kobject *kobj,
				       struct attribute *attr, int n)
{
@@ -161,6 +173,9 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata)
		drvdata->dsb->trig_ts = true;
		drvdata->dsb->trig_type = false;
	}

	if (drvdata->cmb)
		memset(drvdata->cmb, 0, sizeof(struct cmb_dataset));
}

static void set_dsb_mode(struct tpdm_drvdata *drvdata, u32 *val)
@@ -391,6 +406,12 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata)
		if (!drvdata->dsb)
			return -ENOMEM;
	}
	if (tpdm_has_cmb_dataset(drvdata) && (!drvdata->cmb)) {
		drvdata->cmb = devm_kzalloc(drvdata->dev,
						sizeof(*drvdata->cmb), GFP_KERNEL);
		if (!drvdata->cmb)
			return -ENOMEM;
	}
	tpdm_reset_datasets(drvdata);

	return 0;
@@ -729,6 +750,34 @@ static ssize_t dsb_trig_ts_store(struct device *dev,
}
static DEVICE_ATTR_RW(dsb_trig_ts);

static ssize_t cmb_mode_show(struct device *dev,
			     struct device_attribute *attr,
			     char *buf)
{
	struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);

	return sysfs_emit(buf, "%x\n", drvdata->cmb->trace_mode);

}

static ssize_t cmb_mode_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 trace_mode;

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

	spin_lock(&drvdata->spinlock);
	drvdata->cmb->trace_mode = trace_mode;
	spin_unlock(&drvdata->spinlock);
	return size;
}
static DEVICE_ATTR_RW(cmb_mode);

static struct attribute *tpdm_dsb_edge_attrs[] = {
	&dev_attr_ctrl_idx.attr,
	&dev_attr_ctrl_val.attr,
@@ -845,6 +894,11 @@ static struct attribute *tpdm_dsb_attrs[] = {
	NULL,
};

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

static struct attribute_group tpdm_dsb_attr_grp = {
	.attrs = tpdm_dsb_attrs,
	.is_visible = tpdm_dsb_is_visible,
@@ -874,6 +928,11 @@ static struct attribute_group tpdm_dsb_msr_grp = {
	.name = "dsb_msr",
};

static struct attribute_group tpdm_cmb_attr_grp = {
	.attrs = tpdm_cmb_attrs,
	.is_visible = tpdm_cmb_is_visible,
};

static const struct attribute_group *tpdm_attr_grps[] = {
	&tpdm_attr_grp,
	&tpdm_dsb_attr_grp,
@@ -881,6 +940,7 @@ static const struct attribute_group *tpdm_attr_grps[] = {
	&tpdm_dsb_trig_patt_grp,
	&tpdm_dsb_patt_grp,
	&tpdm_dsb_msr_grp,
	&tpdm_cmb_attr_grp,
	NULL,
};

+12 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@

/* Enable bit for CMB subunit */
#define TPDM_CMB_CR_ENA		BIT(0)
/* Trace collection mode for CMB subunit */
#define TPDM_CMB_CR_MODE	BIT(1)

/* DSB Subunit Registers */
#define TPDM_DSB_CR		(0x780)
@@ -181,6 +183,14 @@ struct dsb_dataset {
	bool			trig_type;
};

/**
 * struct cmb_dataset
 * @trace_mode:       Dataset collection mode
 */
struct cmb_dataset {
	u32			trace_mode;
};

/**
 * struct tpdm_drvdata - specifics associated to an TPDM component
 * @base:       memory mapped base address for this component.
@@ -190,6 +200,7 @@ struct dsb_dataset {
 * @enable:     enable status of the component.
 * @datasets:   The datasets types present of the TPDM.
 * @dsb         Specifics associated to TPDM DSB.
 * @cmb         Specifics associated to TPDM CMB.
 * @dsb_msr_num Number of MSR supported by DSB TPDM
 */

@@ -201,6 +212,7 @@ struct tpdm_drvdata {
	bool			enable;
	unsigned long		datasets;
	struct dsb_dataset	*dsb;
	struct cmb_dataset	*cmb;
	u32			dsb_msr_num;
};