static ssize_t mode_store()

in coresight/coresight-etm4x-sysfs.c [291:438]


static ssize_t mode_store(struct device *dev,
			  struct device_attribute *attr,
			  const char *buf, size_t size)
{
	unsigned long val, mode;
	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
	struct etmv4_config *config = &drvdata->config;

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

	spin_lock(&drvdata->spinlock);
	config->mode = val & ETMv4_MODE_ALL;

	if (drvdata->instrp0 == true) {
		/* start by clearing instruction P0 field */
		config->cfg  &= ~(BIT(1) | BIT(2));
		if (config->mode & ETM_MODE_LOAD)
			/* 0b01 Trace load instructions as P0 instructions */
			config->cfg  |= BIT(1);
		if (config->mode & ETM_MODE_STORE)
			/* 0b10 Trace store instructions as P0 instructions */
			config->cfg  |= BIT(2);
		if (config->mode & ETM_MODE_LOAD_STORE)
			/*
			 * 0b11 Trace load and store instructions
			 * as P0 instructions
			 */
			config->cfg  |= BIT(1) | BIT(2);
	}

	/* bit[3], Branch broadcast mode */
	if ((config->mode & ETM_MODE_BB) && (drvdata->trcbb == true))
		config->cfg |= BIT(3);
	else
		config->cfg &= ~BIT(3);

	/* bit[4], Cycle counting instruction trace bit */
	if ((config->mode & ETMv4_MODE_CYCACC) &&
		(drvdata->trccci == true))
		config->cfg |= BIT(4);
	else
		config->cfg &= ~BIT(4);

	/* bit[6], Context ID tracing bit */
	if ((config->mode & ETMv4_MODE_CTXID) && (drvdata->ctxid_size))
		config->cfg |= BIT(6);
	else
		config->cfg &= ~BIT(6);

	if ((config->mode & ETM_MODE_VMID) && (drvdata->vmid_size))
		config->cfg |= BIT(7);
	else
		config->cfg &= ~BIT(7);

	/* bits[10:8], Conditional instruction tracing bit */
	mode = ETM_MODE_COND(config->mode);
	if (drvdata->trccond == true) {
		config->cfg &= ~(BIT(8) | BIT(9) | BIT(10));
		config->cfg |= mode << 8;
	}

	/* bit[11], Global timestamp tracing bit */
	if ((config->mode & ETMv4_MODE_TIMESTAMP) && (drvdata->ts_size))
		config->cfg |= BIT(11);
	else
		config->cfg &= ~BIT(11);

	/* bit[12], Return stack enable bit */
	if ((config->mode & ETM_MODE_RETURNSTACK) &&
					(drvdata->retstack == true))
		config->cfg |= BIT(12);
	else
		config->cfg &= ~BIT(12);

	/* bits[14:13], Q element enable field */
	mode = ETM_MODE_QELEM(config->mode);
	/* start by clearing QE bits */
	config->cfg &= ~(BIT(13) | BIT(14));
	/* if supported, Q elements with instruction counts are enabled */
	if ((mode & BIT(0)) && (drvdata->q_support & BIT(0)))
		config->cfg |= BIT(13);
	/*
	 * if supported, Q elements with and without instruction
	 * counts are enabled
	 */
	if ((mode & BIT(1)) && (drvdata->q_support & BIT(1)))
		config->cfg |= BIT(14);

	/* bit[11], AMBA Trace Bus (ATB) trigger enable bit */
	if ((config->mode & ETM_MODE_ATB_TRIGGER) &&
	    (drvdata->atbtrig == true))
		config->eventctrl1 |= BIT(11);
	else
		config->eventctrl1 &= ~BIT(11);

	/* bit[12], Low-power state behavior override bit */
	if ((config->mode & ETM_MODE_LPOVERRIDE) &&
	    (drvdata->lpoverride == true))
		config->eventctrl1 |= BIT(12);
	else
		config->eventctrl1 &= ~BIT(12);

	/* bit[8], Instruction stall bit */
	if ((config->mode & ETM_MODE_ISTALL_EN) && (drvdata->stallctl == true))
		config->stall_ctrl |= BIT(8);
	else
		config->stall_ctrl &= ~BIT(8);

	/* bit[10], Prioritize instruction trace bit */
	if (config->mode & ETM_MODE_INSTPRIO)
		config->stall_ctrl |= BIT(10);
	else
		config->stall_ctrl &= ~BIT(10);

	/* bit[13], Trace overflow prevention bit */
	if ((config->mode & ETM_MODE_NOOVERFLOW) &&
		(drvdata->nooverflow == true))
		config->stall_ctrl |= BIT(13);
	else
		config->stall_ctrl &= ~BIT(13);

	/* bit[9] Start/stop logic control bit */
	if (config->mode & ETM_MODE_VIEWINST_STARTSTOP)
		config->vinst_ctrl |= BIT(9);
	else
		config->vinst_ctrl &= ~BIT(9);

	/* bit[10], Whether a trace unit must trace a Reset exception */
	if (config->mode & ETM_MODE_TRACE_RESET)
		config->vinst_ctrl |= BIT(10);
	else
		config->vinst_ctrl &= ~BIT(10);

	/* bit[11], Whether a trace unit must trace a system error exception */
	if ((config->mode & ETM_MODE_TRACE_ERR) &&
		(drvdata->trc_error == true))
		config->vinst_ctrl |= BIT(11);
	else
		config->vinst_ctrl &= ~BIT(11);

	if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
		etm4_config_trace_mode(config);

	spin_unlock(&drvdata->spinlock);

	return size;
}