drivers/hwtracing/coresight/coresight-etm4x-sysfs.c

Source file repositories/reference/linux-study-clean/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c

File Facts

System
Linux kernel
Corpus path
drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
Extension
.c
Size
71835 bytes
Lines
2605
Domain
Driver Families
Bucket
drivers/hwtracing
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct etmv4_reg {
	struct coresight_device *csdev;
	u32 offset;
	u32 data;
};

static void do_smp_cross_read(void *data)
{
	struct etmv4_reg *reg = data;

	reg->data = etm4x_relaxed_read32(&reg->csdev->access, reg->offset);
}

static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
{
	struct etmv4_reg reg;

	reg.offset = offset;
	reg.csdev = drvdata->csdev;

	/*
	 * smp cross call ensures the CPU will be powered up before
	 * accessing the ETMv4 trace core registers
	 */
	smp_call_function_single(drvdata->cpu, do_smp_cross_read, &reg, 1);
	return reg.data;
}

static u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
{
	struct dev_ext_attribute *eattr;

	eattr = container_of(attr, struct dev_ext_attribute, attr);
	return (u32)(unsigned long)eattr->var;
}

static ssize_t coresight_etm4x_reg_show(struct device *dev,
					struct device_attribute *d_attr,
					char *buf)
{
	u32 val, offset;
	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);

	offset = coresight_etm4x_attr_to_offset(d_attr);

	pm_runtime_get_sync(dev->parent);
	val = etmv4_cross_read(drvdata, offset);
	pm_runtime_put_sync(dev->parent);

	return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
}

static bool
etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
{
	switch (offset) {
	ETM_COMMON_SYSREG_LIST_CASES
		/*
		 * Common registers to ETE & ETM4x accessible via system
		 * instructions are always implemented.
		 */
		return true;

	ETM4x_ONLY_SYSREG_LIST_CASES
		/*
		 * We only support etm4x and ete. So if the device is not
		 * ETE, it must be ETMv4x.
		 */
		return !etm4x_is_ete(drvdata);

	ETM4x_MMAP_LIST_CASES
		/*
		 * Registers accessible only via memory-mapped registers
		 * must not be accessed via system instructions.
		 * We cannot access the drvdata->csdev here, as this
		 * function is called during the device creation, via
		 * coresight_register() and the csdev is not initialized
		 * until that is done. So rely on the drvdata->base to
		 * detect if we have a memory mapped access.
		 * Also ETE doesn't implement memory mapped access, thus
		 * it is sufficient to check that we are using mmio.
		 */
		return !!drvdata->base;

	ETE_ONLY_SYSREG_LIST_CASES
		return etm4x_is_ete(drvdata);
	}

	return false;
}

Annotation

Implementation Notes