@@ -123,6 +123,7 @@ gt-y += \
gt/intel_ring.o \
gt/intel_ring_submission.o \
gt/intel_rps.o \
+ gt/intel_sa_media.o \
gt/intel_sseu.o \
gt/intel_sseu_debugfs.o \
gt/intel_timeline.o \
@@ -776,10 +776,15 @@ void intel_gt_driver_late_release_all(struct drm_i915_private *i915)
}
}
-static int intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr)
+static int intel_gt_tile_setup(struct intel_gt *gt,
+ phys_addr_t phys_addr,
+ u32 gsi_offset)
{
int ret;
+ /* GSI offset is only applicable for media GTs */
+ drm_WARN_ON(>->i915->drm, gsi_offset);
+
if (!gt_is_root(gt)) {
struct intel_uncore_mmio_debug *mmio_debug;
struct intel_uncore *uncore;
@@ -840,7 +845,7 @@ int intel_gt_probe_all(struct drm_i915_private *i915)
gt->info.engine_mask = RUNTIME_INFO(i915)->platform_engine_mask;
drm_dbg(&i915->drm, "Setting up %s\n", gt->name);
- ret = intel_gt_tile_setup(gt, phys_addr);
+ ret = intel_gt_tile_setup(gt, phys_addr, 0);
if (ret)
return ret;
@@ -873,7 +878,8 @@ int intel_gt_probe_all(struct drm_i915_private *i915)
goto err;
}
- ret = gtdef->setup(gt, phys_addr + gtdef->mapping_base);
+ ret = gtdef->setup(gt, phys_addr + gtdef->mapping_base,
+ gtdef->gsi_offset);
if (ret)
goto err;
@@ -1578,4 +1578,12 @@
#define GEN12_SFC_DONE(n) _MMIO(0x1cc000 + (n) * 0x1000)
+/*
+ * Standalone Media's non-engine GT registers are located at their regular GT
+ * offsets plus 0x380000. This extra offset is stored inside the intel_uncore
+ * structure so that the existing code can be used for both GTs without
+ * modification.
+ */
+#define MTL_MEDIA_GSI_BASE 0x380000
+
#endif /* __INTEL_GT_REGS__ */
new file mode 100644
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <drm/drm_managed.h>
+
+#include "i915_drv.h"
+#include "gt/intel_gt.h"
+#include "gt/intel_sa_media.h"
+
+int intel_sa_mediagt_setup(struct intel_gt *gt, phys_addr_t phys_addr,
+ u32 gsi_offset)
+{
+ struct drm_i915_private *i915 = gt->i915;
+ struct intel_uncore *uncore;
+
+ uncore = drmm_kzalloc(&i915->drm, sizeof(*uncore), GFP_KERNEL);
+ if (!uncore)
+ return -ENOMEM;
+
+ uncore->gsi_offset = gsi_offset;
+
+ intel_gt_common_init_early(gt);
+ intel_uncore_init_early(uncore, gt);
+
+ /*
+ * Standalone media shares the general MMIO space with the primary
+ * GT. We'll re-use the primary GT's mapping.
+ */
+ uncore->regs = i915->uncore.regs;
+ if (drm_WARN_ON(&i915->drm, uncore->regs == NULL))
+ return -EIO;
+
+ gt->uncore = uncore;
+ gt->phys_addr = phys_addr;
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+#ifndef __INTEL_SA_MEDIA__
+#define __INTEL_SA_MEDIA__
+
+#include <linux/types.h>
+
+struct intel_gt;
+
+int intel_sa_mediagt_setup(struct intel_gt *gt, phys_addr_t phys_addr,
+ u32 gsi_offset);
+
+#endif /* __INTEL_SA_MEDIA_H__ */
@@ -26,6 +26,9 @@
#include <drm/drm_drv.h>
#include <drm/i915_pciids.h>
+#include "gt/intel_gt_regs.h"
+#include "gt/intel_sa_media.h"
+
#include "i915_driver.h"
#include "i915_drv.h"
#include "i915_pci.h"
@@ -1115,6 +1118,17 @@ static const struct intel_device_info pvc_info = {
.display.has_cdclk_crawl = 1, \
.__runtime.fbc_mask = BIT(INTEL_FBC_A) | BIT(INTEL_FBC_B)
+static const struct intel_gt_definition xelpmp_extra_gt[] = {
+ {
+ .type = GT_MEDIA,
+ .name = "Standalone Media GT",
+ .setup = intel_sa_mediagt_setup,
+ .gsi_offset = MTL_MEDIA_GSI_BASE,
+ .engine_mask = BIT(VECS0) | BIT(VCS0) | BIT(VCS2),
+ },
+ {}
+};
+
__maybe_unused
static const struct intel_device_info mtl_info = {
XE_HP_FEATURES,
@@ -1128,6 +1142,7 @@ static const struct intel_device_info mtl_info = {
.media.ver = 13,
PLATFORM(INTEL_METEORLAKE),
.display.has_modular_fia = 1,
+ .extra_gt_list = xelpmp_extra_gt,
.has_flat_ccs = 0,
.has_snoop = 1,
.__runtime.memory_regions = REGION_SMEM | REGION_STOLEN_LMEM,
@@ -248,14 +248,17 @@ struct intel_runtime_info {
enum intel_gt_type {
GT_PRIMARY,
GT_TILE,
+ GT_MEDIA,
};
struct intel_gt_definition {
enum intel_gt_type type;
char *name;
int (*setup)(struct intel_gt *gt,
- phys_addr_t phys_addr);
+ phys_addr_t phys_addr,
+ u32 gsi_offset);
u32 mapping_base;
+ u32 gsi_offset;
intel_engine_mask_t engine_mask;
};
@@ -1771,10 +1771,15 @@ __gen2_read(64)
#undef GEN2_READ_FOOTER
#undef GEN2_READ_HEADER
+#define IS_GSI_REG(reg) ((reg) < 0x40000)
+
#define GEN6_READ_HEADER(x) \
- u32 offset = i915_mmio_reg_offset(reg); \
+ u32 offset; \
unsigned long irqflags; \
u##x val = 0; \
+ if (IS_GSI_REG(reg.reg)) \
+ reg.reg += uncore->gsi_offset; \
+ offset = i915_mmio_reg_offset(reg); \
assert_rpm_wakelock_held(uncore->rpm); \
spin_lock_irqsave(&uncore->lock, irqflags); \
unclaimed_reg_debug(uncore, reg, true, true)
@@ -1876,8 +1881,11 @@ __gen2_write(32)
#undef GEN2_WRITE_HEADER
#define GEN6_WRITE_HEADER \
- u32 offset = i915_mmio_reg_offset(reg); \
+ u32 offset; \
unsigned long irqflags; \
+ if (IS_GSI_REG(reg.reg)) \
+ reg.reg += uncore->gsi_offset; \
+ offset = i915_mmio_reg_offset(reg); \
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
assert_rpm_wakelock_held(uncore->rpm); \
spin_lock_irqsave(&uncore->lock, irqflags); \
@@ -2256,6 +2264,10 @@ int intel_uncore_setup_mmio(struct intel_uncore *uncore, phys_addr_t phys_addr)
void intel_uncore_cleanup_mmio(struct intel_uncore *uncore)
{
+ /* The media GT re-uses the primary GT's register mapping */
+ if (uncore->gt->type == GT_MEDIA)
+ return;
+
iounmap(uncore->regs);
}
@@ -135,6 +135,16 @@ struct intel_uncore {
spinlock_t lock; /** lock is also taken in irq contexts. */
+ /*
+ * Do we need to apply an additional offset to reach the beginning
+ * of the basic non-engine GT registers (referred to as "GSI" on
+ * newer platforms, or "GT block" on older platforms)? If so, we'll
+ * track that here and apply it transparently to registers in the
+ * appropriate range to maintain compatibility with our existing
+ * register definitions and GT code.
+ */
+ u32 gsi_offset;
+
unsigned int flags;
#define UNCORE_HAS_FORCEWAKE BIT(0)
#define UNCORE_HAS_FPGA_DBG_UNCLAIMED BIT(1)
@@ -299,14 +309,20 @@ intel_wait_for_register_fw(struct intel_uncore *uncore,
static inline u##x__ __raw_uncore_read##x__(const struct intel_uncore *uncore, \
i915_reg_t reg) \
{ \
- return read##s__(uncore->regs + i915_mmio_reg_offset(reg)); \
+ u32 offset = i915_mmio_reg_offset(reg); \
+ if (offset < 0x40000) \
+ offset += uncore->gsi_offset; \
+ return read##s__(uncore->regs + offset); \
}
#define __raw_write(x__, s__) \
static inline void __raw_uncore_write##x__(const struct intel_uncore *uncore, \
i915_reg_t reg, u##x__ val) \
{ \
- write##s__(val, uncore->regs + i915_mmio_reg_offset(reg)); \
+ u32 offset = i915_mmio_reg_offset(reg); \
+ if (offset < 0x40000) \
+ offset += uncore->gsi_offset; \
+ write##s__(val, uncore->regs + offset); \
}
__raw_read(8, b)
__raw_read(16, w)