summaryrefslogtreecommitdiff
path: root/drivers/perf
diff options
context:
space:
mode:
authorJoakim Zhang <qiangqing.zhang@nxp.com>2019-09-24 14:03:49 +0800
committerJoakim Zhang <qiangqing.zhang@nxp.com>2020-03-04 09:06:04 +0800
commit18081034fd7a136f31e704812d36db0f4122acea (patch)
tree353bbe9fd54a7403b440badea7051223dd817246 /drivers/perf
parentcb1a3f4a797561e1abdf3234b7d6a71f49ddac5d (diff)
MLK-23418-1 perf/imx_ddr: Extend driver for PMU in DRAM Block(DB)
There is a PMU in DB(DRAM Block) which has the same function with PMU in DDR subsystem, the difference is PMU in DB only supports cycles, axid-read, axid-write events. The role of the DB is to route the read/write transaction from connected subsystems to either the DDR subsystem, or to any other subsystems. The AXI IDs used is the one seen at the PORT. e.g. perf stat -a -e imx8_db0/axid-read,axi_mask=0xMMMM,axi_id=0xDDDD,axi_port=0xPP,axi_channel=0xH/ cmd perf stat -a -e imx8_db0/axid-write,axi_mask=0xMMMM,axi_id=0xDDDD,axi_port=0xPP,axi_channel=0xH/ cmd Reviewed-by: Fugang Duan <fugang.duan@nxp.com> Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Diffstat (limited to 'drivers/perf')
-rw-r--r--drivers/perf/fsl_imx8_ddr_perf.c73
1 files changed, 58 insertions, 15 deletions
diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
index 4084470a2af3..4e816dfc5117 100644
--- a/drivers/perf/fsl_imx8_ddr_perf.c
+++ b/drivers/perf/fsl_imx8_ddr_perf.c
@@ -52,31 +52,43 @@
#define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu)
#define DDR_PERF_DEV_NAME "imx8_ddr"
+#define DB_PERF_DEV_NAME "imx8_db"
#define DDR_CPUHP_CB_NAME DDR_PERF_DEV_NAME "_perf_pmu"
static DEFINE_IDA(ddr_ida);
+static DEFINE_IDA(db_ida);
/* DDR Perf hardware feature */
#define DDR_CAP_AXI_ID_FILTER 0x1 /* support AXI ID filter */
#define DDR_CAP_AXI_ID_FILTER_ENHANCED 0x3 /* support enhanced AXI ID filter */
#define DDR_CAP_AXI_ID_PORT_CHANNEL_FILTER 0x4 /* support AXI ID PORT CHANNEL filter */
+/* Perf type */
+#define DDR_PERF_TYPE 0x1 /* ddr Perf */
+#define DB_PERF_TYPE 0x2 /* db Perf */
+
struct fsl_ddr_devtype_data {
unsigned int quirks; /* quirks needed for different DDR Perf core */
+ unsigned int type; /* types of Perf, point the location of Perf */
};
-static const struct fsl_ddr_devtype_data imx8_devtype_data;
+static const struct fsl_ddr_devtype_data imx8_devtype_data = {
+ .type = DDR_PERF_TYPE,
+};
static const struct fsl_ddr_devtype_data imx8m_devtype_data = {
.quirks = DDR_CAP_AXI_ID_FILTER,
+ .type = DDR_PERF_TYPE,
};
static const struct fsl_ddr_devtype_data imx8mp_devtype_data = {
.quirks = DDR_CAP_AXI_ID_FILTER_ENHANCED,
+ .type = DDR_PERF_TYPE,
};
static const struct fsl_ddr_devtype_data imx8dxl_devtype_data = {
.quirks = DDR_CAP_AXI_ID_PORT_CHANNEL_FILTER,
+ .type = DDR_PERF_TYPE,
};
static const struct of_device_id imx_ddr_pmu_dt_ids[] = {
@@ -239,6 +251,18 @@ static struct attribute_group ddr_perf_events_attr_group = {
.attrs = ddr_perf_events_attrs,
};
+static struct attribute *db_perf_events_attrs[] = {
+ IMX8_DDR_PMU_EVENT_ATTR(cycles, EVENT_CYCLES_ID),
+ IMX8_DDR_PMU_EVENT_ATTR(axid-read, 0x41),
+ IMX8_DDR_PMU_EVENT_ATTR(axid-write, 0x42),
+ NULL,
+};
+
+static struct attribute_group db_perf_events_attr_group = {
+ .name = "events",
+ .attrs = db_perf_events_attrs,
+};
+
PMU_FORMAT_ATTR(event, "config:0-7");
PMU_FORMAT_ATTR(axi_id, "config1:0-15");
PMU_FORMAT_ATTR(axi_mask, "config1:16-31");
@@ -259,7 +283,8 @@ static struct attribute_group ddr_perf_format_attr_group = {
.attrs = ddr_perf_format_attrs,
};
-static const struct attribute_group *attr_groups[] = {
+static const struct attribute_group *ddr_attr_groups[] = {
+
&ddr_perf_events_attr_group,
&ddr_perf_format_attr_group,
&ddr_perf_cpumask_attr_group,
@@ -267,6 +292,14 @@ static const struct attribute_group *attr_groups[] = {
NULL,
};
+static const struct attribute_group *db_attr_groups[] = {
+ &db_perf_events_attr_group,
+ &ddr_perf_format_attr_group,
+ &ddr_perf_cpumask_attr_group,
+ &ddr_perf_filter_cap_attr_group,
+ NULL,
+};
+
static bool ddr_perf_is_filtered(struct perf_event *event)
{
return event->attr.config == 0x41 || event->attr.config == 0x42;
@@ -584,14 +617,13 @@ static void ddr_perf_pmu_disable(struct pmu *pmu)
false);
}
-static int ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base,
+static void ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base,
struct device *dev)
{
*pmu = (struct ddr_pmu) {
.pmu = (struct pmu) {
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
.task_ctx_nr = perf_invalid_context,
- .attr_groups = attr_groups,
.event_init = ddr_perf_event_init,
.add = ddr_perf_event_add,
.del = ddr_perf_event_del,
@@ -604,9 +636,6 @@ static int ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base,
.base = base,
.dev = dev,
};
-
- pmu->id = ida_simple_get(&ddr_ida, 0, 0, GFP_KERNEL);
- return pmu->id;
}
static irqreturn_t ddr_perf_irq_handler(int irq, void *p)
@@ -698,7 +727,6 @@ static int ddr_perf_probe(struct platform_device *pdev)
struct device_node *np;
void __iomem *base;
char *name;
- int num;
int ret;
int irq;
@@ -712,18 +740,25 @@ static int ddr_perf_probe(struct platform_device *pdev)
if (!pmu)
return -ENOMEM;
- num = ddr_perf_init(pmu, base, &pdev->dev);
+ ddr_perf_init(pmu, base, &pdev->dev);
platform_set_drvdata(pdev, pmu);
spin_lock_init(&pmu->lock);
- name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DDR_PERF_DEV_NAME "%d",
- num);
+ pmu->devtype_data = of_device_get_match_data(&pdev->dev);
+ if (pmu->devtype_data->type & DDR_PERF_TYPE) {
+ pmu->pmu.attr_groups = ddr_attr_groups;
+ pmu->id = ida_simple_get(&ddr_ida, 0, 0, GFP_KERNEL);
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DDR_PERF_DEV_NAME "%d", pmu->id);
+ } else if (pmu->devtype_data->type & DB_PERF_TYPE) {
+ pmu->pmu.attr_groups = db_attr_groups;
+ pmu->id = ida_simple_get(&db_ida, 0, 0, GFP_KERNEL);
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DB_PERF_DEV_NAME "%d", pmu->id);
+ } else
+ return -EINVAL;
if (!name)
return -ENOMEM;
- pmu->devtype_data = of_device_get_match_data(&pdev->dev);
-
pmu->cpu = raw_smp_processor_id();
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
DDR_CPUHP_CB_NAME,
@@ -775,7 +810,11 @@ ddr_perf_err:
if (pmu->cpuhp_state)
cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node);
- ida_simple_remove(&ddr_ida, pmu->id);
+ if (pmu->devtype_data->type & DDR_PERF_TYPE)
+ ida_simple_remove(&ddr_ida, pmu->id);
+ else
+ ida_simple_remove(&db_ida, pmu->id);
+
dev_warn(&pdev->dev, "i.MX8 DDR Perf PMU failed (%d), disabled\n", ret);
return ret;
}
@@ -789,7 +828,11 @@ static int ddr_perf_remove(struct platform_device *pdev)
perf_pmu_unregister(&pmu->pmu);
- ida_simple_remove(&ddr_ida, pmu->id);
+ if (pmu->devtype_data->type & DDR_PERF_TYPE)
+ ida_simple_remove(&ddr_ida, pmu->id);
+ else
+ ida_simple_remove(&db_ida, pmu->id);
+
return 0;
}