Commit 14f2f9bf authored by Matt Roper's avatar Matt Roper
Browse files

drm/i915/mtl: Add MTL forcewake support



MTL has separate forcewake tables for the primary/render GT and the
media GT; each GT's intel_uncore will use a separate forcewake table and
should only initialize the domains that are relevant to that GT.  The GT
ack register also moves to a new location of (GSI base + 0xDFC) on this
platform.

Note that although our uncore handlers take care of transparently
redirecting all register accesses in the media GT's GSI range to their
new offset at 0x380000, the forcewake ranges listed in the table should
use the final, post-translation offsets.

NOTE:  There are two ranges in the media IP that have multicast
registers where the two register instances reside in different power
wells (either VD0 or VD2).  We don't have an easy way to deal with this
today (and in fact we don't even access these register ranges in the
driver today), so for now we just mark those ranges as FORCEWAKE_ALL
which will cause all of the media power wells to be grabbed, ensuring
proper operation.  If we start reading/writing in those ranges in the
future, we can re-visit whether it's worth adding extra steering
complexity into our forcewake support.

Bspec: 67788, 67789, 52077
Cc: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
Signed-off-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Reviewed-by: default avatarHarish Chegondi <harish.chegondi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220910001631.1986601-1-matthew.d.roper@intel.com
parent 01f0ce3e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -39,6 +39,9 @@
#define FORCEWAKE_ACK_RENDER_GEN9		_MMIO(0xd84)
#define FORCEWAKE_ACK_MEDIA_GEN9		_MMIO(0xd88)

#define FORCEWAKE_ACK_GSC			_MMIO(0xdf8)
#define FORCEWAKE_ACK_GT_MTL			_MMIO(0xdfc)

#define MCFG_MCR_SELECTOR			_MMIO(0xfd0)
#define SF_MCR_SELECTOR				_MMIO(0xfd8)
#define GEN8_MCR_SELECTOR			_MMIO(0xfdc)
@@ -898,6 +901,8 @@
#define FORCEWAKE_MEDIA_VDBOX_GEN11(n)		_MMIO(0xa540 + (n) * 4)
#define FORCEWAKE_MEDIA_VEBOX_GEN11(n)		_MMIO(0xa560 + (n) * 4)

#define FORCEWAKE_REQ_GSC			_MMIO(0xa618)

#define CHV_POWER_SS0_SIG1			_MMIO(0xa720)
#define CHV_POWER_SS0_SIG2			_MMIO(0xa724)
#define CHV_POWER_SS1_SIG1			_MMIO(0xa728)
+247 −11
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ static const char * const forcewake_domain_names[] = {
	"vebox1",
	"vebox2",
	"vebox3",
	"gsc",
};

const char *
@@ -888,10 +889,13 @@ void assert_forcewakes_active(struct intel_uncore *uncore,
	spin_unlock_irq(&uncore->lock);
}

/* We give fast paths for the really cool registers */
/*
 * We give fast paths for the really cool registers.  The second range includes
 * media domains (and the GSC starting from Xe_LPM+)
 */
#define NEEDS_FORCE_WAKE(reg) ({ \
	u32 __reg = (reg); \
	__reg < 0x40000 || __reg >= GEN11_BSD_RING_BASE; \
	__reg < 0x40000 || __reg >= 0x116000; \
})

static int fw_range_cmp(u32 offset, const struct intel_forcewake_range *entry)
@@ -1131,6 +1135,45 @@ static const struct i915_range pvc_shadowed_regs[] = {
	{ .start = 0x1F8510, .end = 0x1F8550 },
};

static const struct i915_range mtl_shadowed_regs[] = {
	{ .start =   0x2030, .end =   0x2030 },
	{ .start =   0x2510, .end =   0x2550 },
	{ .start =   0xA008, .end =   0xA00C },
	{ .start =   0xA188, .end =   0xA188 },
	{ .start =   0xA278, .end =   0xA278 },
	{ .start =   0xA540, .end =   0xA56C },
	{ .start =   0xC050, .end =   0xC050 },
	{ .start =   0xC340, .end =   0xC340 },
	{ .start =   0xC4C8, .end =   0xC4C8 },
	{ .start =   0xC4E0, .end =   0xC4E0 },
	{ .start =   0xC600, .end =   0xC600 },
	{ .start =   0xC658, .end =   0xC658 },
	{ .start =   0xCFD4, .end =   0xCFDC },
	{ .start =  0x22030, .end =  0x22030 },
	{ .start =  0x22510, .end =  0x22550 },
};

static const struct i915_range xelpmp_shadowed_regs[] = {
	{ .start = 0x1C0030, .end = 0x1C0030 },
	{ .start = 0x1C0510, .end = 0x1C0550 },
	{ .start = 0x1C8030, .end = 0x1C8030 },
	{ .start = 0x1C8510, .end = 0x1C8550 },
	{ .start = 0x1D0030, .end = 0x1D0030 },
	{ .start = 0x1D0510, .end = 0x1D0550 },
	{ .start = 0x38A008, .end = 0x38A00C },
	{ .start = 0x38A188, .end = 0x38A188 },
	{ .start = 0x38A278, .end = 0x38A278 },
	{ .start = 0x38A540, .end = 0x38A56C },
	{ .start = 0x38A618, .end = 0x38A618 },
	{ .start = 0x38C050, .end = 0x38C050 },
	{ .start = 0x38C340, .end = 0x38C340 },
	{ .start = 0x38C4C8, .end = 0x38C4C8 },
	{ .start = 0x38C4E0, .end = 0x38C4E4 },
	{ .start = 0x38C600, .end = 0x38C600 },
	{ .start = 0x38C658, .end = 0x38C658 },
	{ .start = 0x38CFD4, .end = 0x38CFDC },
};

static int mmio_range_cmp(u32 key, const struct i915_range *range)
{
	if (key < range->start)
@@ -1679,6 +1722,162 @@ static const struct intel_forcewake_range __pvc_fw_ranges[] = {
	GEN_FW_RANGE(0x3e0000, 0x3effff, FORCEWAKE_GT),
};

static const struct intel_forcewake_range __mtl_fw_ranges[] = {
	GEN_FW_RANGE(0x0, 0xaff, 0),
	GEN_FW_RANGE(0xb00, 0xbff, FORCEWAKE_GT),
	GEN_FW_RANGE(0xc00, 0xfff, 0),
	GEN_FW_RANGE(0x1000, 0x1fff, FORCEWAKE_GT),
	GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER),
	GEN_FW_RANGE(0x2700, 0x2fff, FORCEWAKE_GT),
	GEN_FW_RANGE(0x3000, 0x3fff, FORCEWAKE_RENDER),
	GEN_FW_RANGE(0x4000, 0x51ff, FORCEWAKE_GT), /*
		0x4000 - 0x48ff: render
		0x4900 - 0x51ff: reserved */
	GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), /*
		0x5200 - 0x53ff: render
		0x5400 - 0x54ff: reserved
		0x5500 - 0x7fff: render */
	GEN_FW_RANGE(0x8000, 0x813f, FORCEWAKE_GT),
	GEN_FW_RANGE(0x8140, 0x817f, FORCEWAKE_RENDER), /*
		0x8140 - 0x815f: render
		0x8160 - 0x817f: reserved */
	GEN_FW_RANGE(0x8180, 0x81ff, 0),
	GEN_FW_RANGE(0x8200, 0x94cf, FORCEWAKE_GT), /*
		0x8200 - 0x87ff: gt
		0x8800 - 0x8dff: reserved
		0x8e00 - 0x8f7f: gt
		0x8f80 - 0x8fff: reserved
		0x9000 - 0x947f: gt
		0x9480 - 0x94cf: reserved */
	GEN_FW_RANGE(0x94d0, 0x955f, FORCEWAKE_RENDER),
	GEN_FW_RANGE(0x9560, 0x967f, 0), /*
		0x9560 - 0x95ff: always on
		0x9600 - 0x967f: reserved */
	GEN_FW_RANGE(0x9680, 0x97ff, FORCEWAKE_RENDER), /*
		0x9680 - 0x96ff: render
		0x9700 - 0x97ff: reserved */
	GEN_FW_RANGE(0x9800, 0xcfff, FORCEWAKE_GT), /*
		0x9800 - 0xb4ff: gt
		0xb500 - 0xbfff: reserved
		0xc000 - 0xcfff: gt */
	GEN_FW_RANGE(0xd000, 0xd7ff, 0), /*
		0xd000 - 0xd3ff: always on
		0xd400 - 0xd7ff: reserved */
	GEN_FW_RANGE(0xd800, 0xd87f, FORCEWAKE_RENDER),
	GEN_FW_RANGE(0xd880, 0xdbff, FORCEWAKE_GT),
	GEN_FW_RANGE(0xdc00, 0xdcff, FORCEWAKE_RENDER),
	GEN_FW_RANGE(0xdd00, 0xde7f, FORCEWAKE_GT), /*
		0xdd00 - 0xddff: gt
		0xde00 - 0xde7f: reserved */
	GEN_FW_RANGE(0xde80, 0xe8ff, FORCEWAKE_RENDER), /*
		0xde80 - 0xdfff: render
		0xe000 - 0xe0ff: reserved
		0xe100 - 0xe8ff: render */
	GEN_FW_RANGE(0xe900, 0xe9ff, FORCEWAKE_GT),
	GEN_FW_RANGE(0xea00, 0x147ff, 0), /*
		 0xea00 - 0x11fff: reserved
		0x12000 - 0x127ff: always on
		0x12800 - 0x147ff: reserved */
	GEN_FW_RANGE(0x14800, 0x19fff, FORCEWAKE_GT), /*
		0x14800 - 0x153ff: gt
		0x15400 - 0x19fff: reserved */
	GEN_FW_RANGE(0x1a000, 0x21fff, FORCEWAKE_RENDER), /*
		0x1a000 - 0x1bfff: render
		0x1c000 - 0x21fff: reserved */
	GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_GT),
	GEN_FW_RANGE(0x24000, 0x2ffff, 0), /*
		0x24000 - 0x2407f: always on
		0x24080 - 0x2ffff: reserved */
	GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_GT)
};

/*
 * Note that the register ranges here are the final offsets after
 * translation of the GSI block to the 0x380000 offset.
 *
 * NOTE:  There are a couple MCR ranges near the bottom of this table
 * that need to power up either VD0 or VD2 depending on which replicated
 * instance of the register we're trying to access.  Our forcewake logic
 * at the moment doesn't have a good way to take steering into consideration,
 * and the driver doesn't even access any registers in those ranges today,
 * so for now we just mark those ranges as FORCEWAKE_ALL.  That will ensure
 * proper operation if we do start using the ranges in the future, and we
 * can determine at that time whether it's worth adding extra complexity to
 * the forcewake handling to take steering into consideration.
 */
static const struct intel_forcewake_range __xelpmp_fw_ranges[] = {
	GEN_FW_RANGE(0x0, 0x115fff, 0), /* render GT range */
	GEN_FW_RANGE(0x116000, 0x11ffff, FORCEWAKE_GSC), /*
		0x116000 - 0x117fff: gsc
		0x118000 - 0x119fff: reserved
		0x11a000 - 0x11efff: gsc
		0x11f000 - 0x11ffff: reserved */
	GEN_FW_RANGE(0x120000, 0x1bffff, 0), /* non-GT range */
	GEN_FW_RANGE(0x1c0000, 0x1c7fff, FORCEWAKE_MEDIA_VDBOX0), /*
		0x1c0000 - 0x1c3dff: VD0
		0x1c3e00 - 0x1c3eff: reserved
		0x1c3f00 - 0x1c3fff: VD0
		0x1c4000 - 0x1c7fff: reserved */
	GEN_FW_RANGE(0x1c8000, 0x1cbfff, FORCEWAKE_MEDIA_VEBOX0), /*
		0x1c8000 - 0x1ca0ff: VE0
		0x1ca100 - 0x1cbfff: reserved */
	GEN_FW_RANGE(0x1cc000, 0x1cffff, FORCEWAKE_MEDIA_VDBOX0), /*
		0x1cc000 - 0x1cdfff: VD0
		0x1ce000 - 0x1cffff: reserved */
	GEN_FW_RANGE(0x1d0000, 0x1d7fff, FORCEWAKE_MEDIA_VDBOX2), /*
		0x1d0000 - 0x1d3dff: VD2
		0x1d3e00 - 0x1d3eff: reserved
		0x1d4000 - 0x1d7fff: VD2 */
	GEN_FW_RANGE(0x1d8000, 0x1da0ff, FORCEWAKE_MEDIA_VEBOX1),
	GEN_FW_RANGE(0x1da100, 0x380aff, 0), /*
		0x1da100 - 0x23ffff: reserved
		0x240000 - 0x37ffff: non-GT range
		0x380000 - 0x380aff: reserved */
	GEN_FW_RANGE(0x380b00, 0x380bff, FORCEWAKE_GT),
	GEN_FW_RANGE(0x380c00, 0x380fff, 0),
	GEN_FW_RANGE(0x381000, 0x38817f, FORCEWAKE_GT), /*
		0x381000 - 0x381fff: gt
		0x382000 - 0x383fff: reserved
		0x384000 - 0x384aff: gt
		0x384b00 - 0x3851ff: reserved
		0x385200 - 0x3871ff: gt
		0x387200 - 0x387fff: reserved
		0x388000 - 0x38813f: gt
		0x388140 - 0x38817f: reserved */
	GEN_FW_RANGE(0x388180, 0x3882ff, 0), /*
		0x388180 - 0x3881ff: always on
		0x388200 - 0x3882ff: reserved */
	GEN_FW_RANGE(0x388300, 0x38955f, FORCEWAKE_GT), /*
		0x388300 - 0x38887f: gt
		0x388880 - 0x388fff: reserved
		0x389000 - 0x38947f: gt
		0x389480 - 0x38955f: reserved */
	GEN_FW_RANGE(0x389560, 0x389fff, 0), /*
		0x389560 - 0x3895ff: always on
		0x389600 - 0x389fff: reserved */
	GEN_FW_RANGE(0x38a000, 0x38cfff, FORCEWAKE_GT), /*
		0x38a000 - 0x38afff: gt
		0x38b000 - 0x38bfff: reserved
		0x38c000 - 0x38cfff: gt */
	GEN_FW_RANGE(0x38d000, 0x38d11f, 0),
	GEN_FW_RANGE(0x38d120, 0x391fff, FORCEWAKE_GT), /*
		0x38d120 - 0x38dfff: gt
		0x38e000 - 0x38efff: reserved
		0x38f000 - 0x38ffff: gt
		0x389000 - 0x391fff: reserved */
	GEN_FW_RANGE(0x392000, 0x392fff, 0), /*
		0x392000 - 0x3927ff: always on
		0x392800 - 0x292fff: reserved */
	GEN_FW_RANGE(0x393000, 0x3931ff, FORCEWAKE_GT),
	GEN_FW_RANGE(0x393200, 0x39323f, FORCEWAKE_ALL), /* instance-based, see note above */
	GEN_FW_RANGE(0x393240, 0x3933ff, FORCEWAKE_GT),
	GEN_FW_RANGE(0x393400, 0x3934ff, FORCEWAKE_ALL), /* instance-based, see note above */
	GEN_FW_RANGE(0x393500, 0x393c7f, 0), /*
		0x393500 - 0x393bff: reserved
		0x393c00 - 0x393c7f: always on */
	GEN_FW_RANGE(0x393c80, 0x393dff, FORCEWAKE_GT),
};

static void
ilk_dummy_write(struct intel_uncore *uncore)
{
@@ -2021,6 +2220,7 @@ static int __fw_domain_init(struct intel_uncore *uncore,
	BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX1 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX1));
	BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX2 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX2));
	BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX3 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX3));
	BUILD_BUG_ON(FORCEWAKE_GSC != (1 << FW_DOMAIN_ID_GSC));

	d->mask = BIT(domain_id);

@@ -2085,18 +2285,27 @@ static int intel_uncore_fw_domains_init(struct intel_uncore *uncore)
	(ret ?: (ret = __fw_domain_init((uncore__), (id__), (set__), (ack__))))

	if (GRAPHICS_VER(i915) >= 11) {
		/* we'll prune the domains of missing engines later */
		intel_engine_mask_t emask = INTEL_INFO(i915)->platform_engine_mask;
		intel_engine_mask_t emask;
		int i;

		/* we'll prune the domains of missing engines later */
		emask = uncore->gt->info.engine_mask;

		uncore->fw_get_funcs = &uncore_get_fallback;
		fw_domain_init(uncore, FW_DOMAIN_ID_RENDER,
			       FORCEWAKE_RENDER_GEN9,
			       FORCEWAKE_ACK_RENDER_GEN9);
		if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
			fw_domain_init(uncore, FW_DOMAIN_ID_GT,
				       FORCEWAKE_GT_GEN9,
				       FORCEWAKE_ACK_GT_MTL);
		else
			fw_domain_init(uncore, FW_DOMAIN_ID_GT,
				       FORCEWAKE_GT_GEN9,
				       FORCEWAKE_ACK_GT_GEN9);

		if (RCS_MASK(uncore->gt) || CCS_MASK(uncore->gt))
			fw_domain_init(uncore, FW_DOMAIN_ID_RENDER,
				       FORCEWAKE_RENDER_GEN9,
				       FORCEWAKE_ACK_RENDER_GEN9);

		for (i = 0; i < I915_MAX_VCS; i++) {
			if (!__HAS_ENGINE(emask, _VCS(i)))
				continue;
@@ -2113,6 +2322,10 @@ static int intel_uncore_fw_domains_init(struct intel_uncore *uncore)
				       FORCEWAKE_MEDIA_VEBOX_GEN11(i),
				       FORCEWAKE_ACK_MEDIA_VEBOX_GEN11(i));
		}

		if (uncore->gt->type == GT_MEDIA)
			fw_domain_init(uncore, FW_DOMAIN_ID_GSC,
				       FORCEWAKE_REQ_GSC, FORCEWAKE_ACK_GSC);
	} else if (IS_GRAPHICS_VER(i915, 9, 10)) {
		uncore->fw_get_funcs = &uncore_get_fallback;
		fw_domain_init(uncore, FW_DOMAIN_ID_RENDER,
@@ -2300,6 +2513,22 @@ static void uncore_raw_init(struct intel_uncore *uncore)
	}
}

static int uncore_media_forcewake_init(struct intel_uncore *uncore)
{
	struct drm_i915_private *i915 = uncore->i915;

	if (MEDIA_VER(i915) >= 13) {
		ASSIGN_FW_DOMAINS_TABLE(uncore, __xelpmp_fw_ranges);
		ASSIGN_SHADOW_TABLE(uncore, xelpmp_shadowed_regs);
		ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
	} else {
		MISSING_CASE(MEDIA_VER(i915));
		return -ENODEV;
	}

	return 0;
}

static int uncore_forcewake_init(struct intel_uncore *uncore)
{
	struct drm_i915_private *i915 = uncore->i915;
@@ -2314,7 +2543,14 @@ static int uncore_forcewake_init(struct intel_uncore *uncore)

	ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable);

	if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 60)) {
	if (uncore->gt->type == GT_MEDIA)
		return uncore_media_forcewake_init(uncore);

	if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)) {
		ASSIGN_FW_DOMAINS_TABLE(uncore, __mtl_fw_ranges);
		ASSIGN_SHADOW_TABLE(uncore, mtl_shadowed_regs);
		ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
	} else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 60)) {
		ASSIGN_FW_DOMAINS_TABLE(uncore, __pvc_fw_ranges);
		ASSIGN_SHADOW_TABLE(uncore, pvc_shadowed_regs);
		ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
+2 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ enum forcewake_domain_id {
	FW_DOMAIN_ID_MEDIA_VEBOX1,
	FW_DOMAIN_ID_MEDIA_VEBOX2,
	FW_DOMAIN_ID_MEDIA_VEBOX3,
	FW_DOMAIN_ID_GSC,

	FW_DOMAIN_ID_COUNT
};
@@ -82,6 +83,7 @@ enum forcewake_domains {
	FORCEWAKE_MEDIA_VEBOX1	= BIT(FW_DOMAIN_ID_MEDIA_VEBOX1),
	FORCEWAKE_MEDIA_VEBOX2	= BIT(FW_DOMAIN_ID_MEDIA_VEBOX2),
	FORCEWAKE_MEDIA_VEBOX3	= BIT(FW_DOMAIN_ID_MEDIA_VEBOX3),
	FORCEWAKE_GSC		= BIT(FW_DOMAIN_ID_GSC),

	FORCEWAKE_ALL = BIT(FW_DOMAIN_ID_COUNT) - 1,
};
+4 −0
Original line number Diff line number Diff line
@@ -70,6 +70,8 @@ static int intel_shadow_table_check(void)
		{ gen12_shadowed_regs, ARRAY_SIZE(gen12_shadowed_regs) },
		{ dg2_shadowed_regs, ARRAY_SIZE(dg2_shadowed_regs) },
		{ pvc_shadowed_regs, ARRAY_SIZE(pvc_shadowed_regs) },
		{ mtl_shadowed_regs, ARRAY_SIZE(mtl_shadowed_regs) },
		{ xelpmp_shadowed_regs, ARRAY_SIZE(xelpmp_shadowed_regs) },
	};
	const struct i915_range *range;
	unsigned int i, j;
@@ -117,6 +119,8 @@ int intel_uncore_mock_selftests(void)
		{ __gen12_fw_ranges, ARRAY_SIZE(__gen12_fw_ranges), true },
		{ __xehp_fw_ranges, ARRAY_SIZE(__xehp_fw_ranges), true },
		{ __pvc_fw_ranges, ARRAY_SIZE(__pvc_fw_ranges), true },
		{ __mtl_fw_ranges, ARRAY_SIZE(__mtl_fw_ranges), true },
		{ __xelpmp_fw_ranges, ARRAY_SIZE(__xelpmp_fw_ranges), true },
	};
	int err, i;