#include <linux/perf_event.h>
 
 /* Performance monitor configuration */
-#define PMCFG1                         0x00
-#define PMCFG1_RD_TRANS_FILT_EN        BIT(31)
-#define PMCFG1_WR_TRANS_FILT_EN        BIT(30)
-#define PMCFG1_RD_BT_FILT_EN           BIT(29)
-#define PMCFG1_ID_MASK                 GENMASK(17, 0)
+#define PMCFG1                         0x00
+#define MX93_PMCFG1_RD_TRANS_FILT_EN   BIT(31)
+#define MX93_PMCFG1_WR_TRANS_FILT_EN   BIT(30)
+#define MX93_PMCFG1_RD_BT_FILT_EN      BIT(29)
+#define MX93_PMCFG1_ID_MASK            GENMASK(17, 0)
 
-#define PMCFG2                         0x04
-#define PMCFG2_ID                      GENMASK(17, 0)
+#define PMCFG2                         0x04
+#define MX93_PMCFG2_ID                 GENMASK(17, 0)
 
 /* Global control register affects all counters and takes priority over local control registers */
 #define PMGC0          0x40
        .identifier = "imx93",
 };
 
+static inline bool is_imx93(struct ddr_pmu *pmu)
+{
+       return pmu->devtype_data == &imx93_devtype_data;
+}
+
 static const struct of_device_id imx_ddr_pmu_dt_ids[] = {
        {.compatible = "fsl,imx93-ddr-pmu", .data = &imx93_devtype_data},
        { /* sentinel */ }
        .attrs = ddr_perf_cpumask_attrs,
 };
 
+struct imx9_pmu_events_attr {
+       struct device_attribute attr;
+       u64 id;
+       const void *devtype_data;
+};
+
 static ssize_t ddr_pmu_event_show(struct device *dev,
                                  struct device_attribute *attr, char *page)
 {
-       struct perf_pmu_events_attr *pmu_attr;
+       struct imx9_pmu_events_attr *pmu_attr;
 
-       pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+       pmu_attr = container_of(attr, struct imx9_pmu_events_attr, attr);
        return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
 }
 
 #define COUNTER_OFFSET_IN_EVENT        8
 #define ID(counter, id) ((counter << COUNTER_OFFSET_IN_EVENT) | id)
 
-#define IMX9_DDR_PMU_EVENT_ATTR(_name, _id)                            \
-       (&((struct perf_pmu_events_attr[]) {                            \
+#define DDR_PMU_EVENT_ATTR_COMM(_name, _id, _data)                     \
+       (&((struct imx9_pmu_events_attr[]) {                            \
                { .attr = __ATTR(_name, 0444, ddr_pmu_event_show, NULL),\
-                 .id = _id, }                                          \
+                 .id = _id,                                            \
+                 .devtype_data = _data, }                              \
        })[0].attr.attr)
 
+#define IMX9_DDR_PMU_EVENT_ATTR(_name, _id)                            \
+       DDR_PMU_EVENT_ATTR_COMM(_name, _id, NULL)
+
+#define IMX93_DDR_PMU_EVENT_ATTR(_name, _id)                           \
+       DDR_PMU_EVENT_ATTR_COMM(_name, _id, &imx93_devtype_data)
+
 static struct attribute *ddr_perf_events_attrs[] = {
        /* counter0 cycles event */
        IMX9_DDR_PMU_EVENT_ATTR(cycles, 0),
        IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_6, ID(2, 70)),
        IMX9_DDR_PMU_EVENT_ATTR(ddrc_ld_wiq_7, ID(2, 71)),
        IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_empty, ID(2, 72)),
-       IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_trans_filt, ID(2, 73)),
+       IMX93_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_trans_filt, ID(2, 73)),   /* imx93 specific*/
 
        /* counter3 specific events */
        IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_0, ID(3, 64)),
        IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_6, ID(3, 70)),
        IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_collision_7, ID(3, 71)),
        IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_full, ID(3, 72)),
-       IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_wr_trans_filt, ID(3, 73)),
+       IMX93_DDR_PMU_EVENT_ATTR(eddrtq_pm_wr_trans_filt, ID(3, 73)),   /* imx93 specific*/
 
        /* counter4 specific events */
        IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_0, ID(4, 64)),
        IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_6, ID(4, 70)),
        IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_row_open_7, ID(4, 71)),
        IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pmon_ld_rdq2_rmw, ID(4, 72)),
-       IMX9_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt, ID(4, 73)),
+       IMX93_DDR_PMU_EVENT_ATTR(eddrtq_pm_rd_beat_filt, ID(4, 73)),    /* imx93 specific*/
 
        /* counter5 specific events */
        IMX9_DDR_PMU_EVENT_ATTR(ddrc_qx_valid_start_0, ID(5, 64)),
        NULL,
 };
 
+static umode_t
+ddr_perf_events_attrs_is_visible(struct kobject *kobj,
+                                      struct attribute *attr, int unused)
+{
+       struct pmu *pmu = dev_get_drvdata(kobj_to_dev(kobj));
+       struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu);
+       struct imx9_pmu_events_attr *eattr;
+
+       eattr = container_of(attr, typeof(*eattr), attr.attr);
+
+       if (!eattr->devtype_data)
+               return attr->mode;
+
+       if (eattr->devtype_data != ddr_pmu->devtype_data)
+               return 0;
+
+       return attr->mode;
+}
+
 static const struct attribute_group ddr_perf_events_attr_group = {
        .name = "events",
        .attrs = ddr_perf_events_attrs,
+       .is_visible = ddr_perf_events_attrs_is_visible,
 };
 
 PMU_FORMAT_ATTR(event, "config:0-7,16-23");
        }
 }
 
-static void ddr_perf_monitor_config(struct ddr_pmu *pmu, int event,
-                                   int counter, int axi_id, int axi_mask)
+static void imx93_ddr_perf_monitor_config(struct ddr_pmu *pmu, int event,
+                                         int counter, int axi_id, int axi_mask)
 {
        u32 pmcfg1, pmcfg2;
+       u32 mask[] = {  MX93_PMCFG1_RD_TRANS_FILT_EN,
+                       MX93_PMCFG1_WR_TRANS_FILT_EN,
+                       MX93_PMCFG1_RD_BT_FILT_EN };
 
        pmcfg1 = readl_relaxed(pmu->base + PMCFG1);
 
-       if (counter == 2 && event == 73)
-               pmcfg1 |= PMCFG1_RD_TRANS_FILT_EN;
-       else if (counter == 2 && event != 73)
-               pmcfg1 &= ~PMCFG1_RD_TRANS_FILT_EN;
-
-       if (counter == 3 && event == 73)
-               pmcfg1 |= PMCFG1_WR_TRANS_FILT_EN;
-       else if (counter == 3 && event != 73)
-               pmcfg1 &= ~PMCFG1_WR_TRANS_FILT_EN;
-
-       if (counter == 4 && event == 73)
-               pmcfg1 |= PMCFG1_RD_BT_FILT_EN;
-       else if (counter == 4 && event != 73)
-               pmcfg1 &= ~PMCFG1_RD_BT_FILT_EN;
+       if (counter >= 2 && counter <= 4)
+               pmcfg1 = event == 73 ? pmcfg1 | mask[counter - 2] :
+                               pmcfg1 & ~mask[counter - 2];
 
-       pmcfg1 &= ~FIELD_PREP(PMCFG1_ID_MASK, 0x3FFFF);
-       pmcfg1 |= FIELD_PREP(PMCFG1_ID_MASK, axi_mask);
-       writel(pmcfg1, pmu->base + PMCFG1);
+       pmcfg1 &= ~FIELD_PREP(MX93_PMCFG1_ID_MASK, 0x3FFFF);
+       pmcfg1 |= FIELD_PREP(MX93_PMCFG1_ID_MASK, axi_mask);
+       writel_relaxed(pmcfg1, pmu->base + PMCFG1);
 
        pmcfg2 = readl_relaxed(pmu->base + PMCFG2);
-       pmcfg2 &= ~FIELD_PREP(PMCFG2_ID, 0x3FFFF);
-       pmcfg2 |= FIELD_PREP(PMCFG2_ID, axi_id);
-       writel(pmcfg2, pmu->base + PMCFG2);
+       pmcfg2 &= ~FIELD_PREP(MX93_PMCFG2_ID, 0x3FFFF);
+       pmcfg2 |= FIELD_PREP(MX93_PMCFG2_ID, axi_id);
+       writel_relaxed(pmcfg2, pmu->base + PMCFG2);
 }
 
 static void ddr_perf_event_update(struct perf_event *event)
                ddr_perf_event_start(event, flags);
 
        /* read trans, write trans, read beat */
-       ddr_perf_monitor_config(pmu, event_id, counter, cfg1, cfg2);
+       imx93_ddr_perf_monitor_config(pmu, event_id, counter, cfg1, cfg2);
 
        return 0;
 }