The Sapphire Rapids IMC provides the interface to the DRAM and
communicates to the rest of the uncore through the M2M block.
The layout of the control registers for a IMC uncore unit is a little
bit different from the generic one. There is a fixed counter for IMC.
So a specific format and ops are required. Expose the common MMIO ops
which can be reused.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Link: https://lore.kernel.org/r/1625087320-194204-8-git-send-email-kan.liang@linux.intel.com
        return type->box_ctls[box->dieid] + type->mmio_offsets[box->pmu->pmu_idx];
 }
 
-static void intel_generic_uncore_mmio_init_box(struct intel_uncore_box *box)
+void intel_generic_uncore_mmio_init_box(struct intel_uncore_box *box)
 {
        unsigned int box_ctl = generic_uncore_mmio_box_ctl(box);
        struct intel_uncore_type *type = box->pmu->type;
        writel(GENERIC_PMON_BOX_CTL_INT, box->io_addr);
 }
 
-static void intel_generic_uncore_mmio_disable_box(struct intel_uncore_box *box)
+void intel_generic_uncore_mmio_disable_box(struct intel_uncore_box *box)
 {
        if (!box->io_addr)
                return;
        writel(GENERIC_PMON_BOX_CTL_FRZ, box->io_addr);
 }
 
-static void intel_generic_uncore_mmio_enable_box(struct intel_uncore_box *box)
+void intel_generic_uncore_mmio_enable_box(struct intel_uncore_box *box)
 {
        if (!box->io_addr)
                return;
        writel(hwc->config, box->io_addr + hwc->config_base);
 }
 
-static void intel_generic_uncore_mmio_disable_event(struct intel_uncore_box *box,
-                                             struct perf_event *event)
+void intel_generic_uncore_mmio_disable_event(struct intel_uncore_box *box,
+                                            struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
 
 
 void intel_generic_uncore_msr_disable_box(struct intel_uncore_box *box);
 void intel_generic_uncore_msr_enable_box(struct intel_uncore_box *box);
 
+void intel_generic_uncore_mmio_init_box(struct intel_uncore_box *box);
+void intel_generic_uncore_mmio_disable_box(struct intel_uncore_box *box);
+void intel_generic_uncore_mmio_enable_box(struct intel_uncore_box *box);
+void intel_generic_uncore_mmio_disable_event(struct intel_uncore_box *box,
+                                            struct perf_event *event);
+
 struct intel_uncore_type **
 intel_uncore_generic_init_uncores(enum uncore_access_type type_id);
 
        .name                   = "pcu",
 };
 
+static void spr_uncore_mmio_enable_event(struct intel_uncore_box *box,
+                                        struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (!box->io_addr)
+               return;
+
+       if (uncore_pmc_fixed(hwc->idx))
+               writel(SNBEP_PMON_CTL_EN, box->io_addr + hwc->config_base);
+       else
+               writel(hwc->config, box->io_addr + hwc->config_base);
+}
+
+static struct intel_uncore_ops spr_uncore_mmio_ops = {
+       .init_box               = intel_generic_uncore_mmio_init_box,
+       .exit_box               = uncore_mmio_exit_box,
+       .disable_box            = intel_generic_uncore_mmio_disable_box,
+       .enable_box             = intel_generic_uncore_mmio_enable_box,
+       .disable_event          = intel_generic_uncore_mmio_disable_event,
+       .enable_event           = spr_uncore_mmio_enable_event,
+       .read_counter           = uncore_mmio_read_counter,
+};
+
+static struct intel_uncore_type spr_uncore_imc = {
+       SPR_UNCORE_COMMON_FORMAT(),
+       .name                   = "imc",
+       .fixed_ctr_bits         = 48,
+       .fixed_ctr              = SNR_IMC_MMIO_PMON_FIXED_CTR,
+       .fixed_ctl              = SNR_IMC_MMIO_PMON_FIXED_CTL,
+       .ops                    = &spr_uncore_mmio_ops,
+};
+
 #define UNCORE_SPR_NUM_UNCORE_TYPES            12
 
 static struct intel_uncore_type *spr_uncores[UNCORE_SPR_NUM_UNCORE_TYPES] = {
        &spr_uncore_m2pcie,
        &spr_uncore_pcu,
        NULL,
-       NULL,
+       &spr_uncore_imc,
        NULL,
        NULL,
        NULL,