drivers/perf/fsl_imx8_ddr_perf.c

Source file repositories/reference/linux-study-clean/drivers/perf/fsl_imx8_ddr_perf.c

File Facts

System
Linux kernel
Corpus path
drivers/perf/fsl_imx8_ddr_perf.c
Extension
.c
Size
24870 bytes
Lines
918
Domain
Driver Families
Bucket
drivers/perf
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 fsl_ddr_devtype_data {
	unsigned int quirks;    /* quirks needed for different DDR Perf core */
	const char *identifier;	/* system PMU identifier for userspace */
	enum fsl_ddr_type type;	/* types of Perf, ddr or db */
};

static const struct fsl_ddr_devtype_data imx8_devtype_data;

static const struct fsl_ddr_devtype_data imx8m_devtype_data = {
	.quirks = DDR_CAP_AXI_ID_FILTER,
};

static const struct fsl_ddr_devtype_data imx8mq_devtype_data = {
	.quirks = DDR_CAP_AXI_ID_FILTER,
	.identifier = "i.MX8MQ",
};

static const struct fsl_ddr_devtype_data imx8mm_devtype_data = {
	.quirks = DDR_CAP_AXI_ID_FILTER,
	.identifier = "i.MX8MM",
};

static const struct fsl_ddr_devtype_data imx8mn_devtype_data = {
	.quirks = DDR_CAP_AXI_ID_FILTER,
	.identifier = "i.MX8MN",
};

static const struct fsl_ddr_devtype_data imx8mp_devtype_data = {
	.quirks = DDR_CAP_AXI_ID_FILTER_ENHANCED,
	.identifier = "i.MX8MP",
};

static const struct fsl_ddr_devtype_data imx8dxl_devtype_data = {
	.quirks = DDR_CAP_AXI_ID_PORT_CHANNEL_FILTER,
	.identifier = "i.MX8DXL",
};

static const struct fsl_ddr_devtype_data imx8dxl_db_devtype_data = {
	.quirks = DDR_CAP_AXI_ID_PORT_CHANNEL_FILTER,
	.identifier = "i.MX8DXL",
	.type = DB_PERF_TYPE,
};

static const struct of_device_id imx_ddr_pmu_dt_ids[] = {
	{ .compatible = "fsl,imx8-ddr-pmu", .data = &imx8_devtype_data},
	{ .compatible = "fsl,imx8m-ddr-pmu", .data = &imx8m_devtype_data},
	{ .compatible = "fsl,imx8mq-ddr-pmu", .data = &imx8mq_devtype_data},
	{ .compatible = "fsl,imx8mm-ddr-pmu", .data = &imx8mm_devtype_data},
	{ .compatible = "fsl,imx8mn-ddr-pmu", .data = &imx8mn_devtype_data},
	{ .compatible = "fsl,imx8mp-ddr-pmu", .data = &imx8mp_devtype_data},
	{ .compatible = "fsl,imx8dxl-ddr-pmu", .data = &imx8dxl_devtype_data},
	{ .compatible = "fsl,imx8dxl-db-pmu", .data = &imx8dxl_db_devtype_data},
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, imx_ddr_pmu_dt_ids);

struct ddr_pmu {
	struct pmu pmu;
	void __iomem *base;
	unsigned int cpu;
	struct	hlist_node node;
	struct	device *dev;
	struct perf_event *events[NUM_COUNTERS];
	enum cpuhp_state cpuhp_state;
	const struct fsl_ddr_devtype_data *devtype_data;
	int irq;
	int id;
	int active_counter;
};

static ssize_t ddr_perf_identifier_show(struct device *dev,
					struct device_attribute *attr,
					char *page)
{
	struct ddr_pmu *pmu = dev_get_drvdata(dev);

	return sysfs_emit(page, "%s\n", pmu->devtype_data->identifier);
}

static umode_t ddr_perf_identifier_attr_visible(struct kobject *kobj,
						struct attribute *attr,
						int n)
{
	struct device *dev = kobj_to_dev(kobj);
	struct ddr_pmu *pmu = dev_get_drvdata(dev);

	if (!pmu->devtype_data->identifier)
		return 0;
	return attr->mode;
};

Annotation

Implementation Notes