Commit 811aa4d2 authored by Matt Roper's avatar Matt Roper Committed by Rodrigo Vivi

drm/xe/xe2: Program PAT tables

The PAT tables become significantly more complicated on Xe2 platforms.
They now control L3, L4, and coherency settings, as well as additional
characteristics such as compression.

Aside from the main PAT table, there's an additional register that
also needs to be programmed with PAT settings for PCI Address
Translation Services.

Bspec: 71582
Signed-off-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Reviewed-by: default avatarBalasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
Link: https://lore.kernel.org/r/20231006182325.3617685-1-lucas.demarchi@intel.comSigned-off-by: default avatarLucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent cf0b9e94
......@@ -10,10 +10,18 @@
#include "xe_gt_mcr.h"
#include "xe_mmio.h"
#define _PAT_ATS 0x47fc
#define _PAT_INDEX(index) _PICK_EVEN_2RANGES(index, 8, \
0x4800, 0x4804, \
0x4848, 0x484c)
#define XE2_NO_PROMOTE REG_BIT(10)
#define XE2_COMP_EN REG_BIT(9)
#define XE2_L3_CLOS REG_GENMASK(7, 6)
#define XE2_L3_POLICY REG_GENMASK(5, 4)
#define XE2_L4_POLICY REG_GENMASK(3, 2)
#define XE2_COH_MODE REG_GENMASK(1, 0)
#define XELPG_L4_POLICY_MASK REG_GENMASK(3, 2)
#define XELPG_PAT_3_UC REG_FIELD_PREP(XELPG_L4_POLICY_MASK, 3)
#define XELPG_PAT_1_WT REG_FIELD_PREP(XELPG_L4_POLICY_MASK, 1)
......@@ -67,6 +75,64 @@ static const u32 xelpg_pat_table[] = {
[4] = XELPG_PAT_0_WB | XELPG_3_COH_2W,
};
/*
* The Xe2 table is getting large/complicated so it's easier to review if
* provided in a form that exactly matches the bspec's formatting. The meaning
* of the fields here are:
* - no_promote: 0=promotable, 1=no promote
* - comp_en: 0=disable, 1=enable
* - l3clos: L3 class of service (0-3)
* - l3_policy: 0=WB, 1=XD ("WB - Transient Display"), 3=UC
* - l4_policy: 0=WB, 1=WT, 3=UC
* - coh_mode: 0=no snoop, 2=1-way coherent, 3=2-way coherent
*
* Reserved entries should be programmed with the maximum caching, minimum
* coherency (which matches an all-0's encoding), so we can just omit them
* in the table.
*/
#define XE2_PAT(no_promote, comp_en, l3clos, l3_policy, l4_policy, coh_mode) \
(no_promote ? XE2_NO_PROMOTE : 0) | \
(comp_en ? XE2_COMP_EN : 0) | \
REG_FIELD_PREP(XE2_L3_CLOS, l3clos) | \
REG_FIELD_PREP(XE2_L3_POLICY, l3_policy) | \
REG_FIELD_PREP(XE2_L4_POLICY, l4_policy) | \
REG_FIELD_PREP(XE2_COH_MODE, coh_mode)
static const u32 xe2_pat_table[] = {
[ 0] = XE2_PAT( 0, 0, 0, 0, 3, 0 ),
[ 1] = XE2_PAT( 0, 0, 0, 0, 3, 2 ),
[ 2] = XE2_PAT( 0, 0, 0, 0, 3, 3 ),
[ 3] = XE2_PAT( 0, 0, 0, 3, 3, 0 ),
[ 4] = XE2_PAT( 0, 0, 0, 3, 0, 2 ),
[ 5] = XE2_PAT( 0, 0, 0, 3, 3, 2 ),
[ 6] = XE2_PAT( 1, 0, 0, 1, 3, 0 ),
[ 7] = XE2_PAT( 0, 0, 0, 3, 0, 3 ),
[ 8] = XE2_PAT( 0, 0, 0, 3, 0, 0 ),
[ 9] = XE2_PAT( 0, 1, 0, 0, 3, 0 ),
[10] = XE2_PAT( 0, 1, 0, 3, 0, 0 ),
[11] = XE2_PAT( 1, 1, 0, 1, 3, 0 ),
[12] = XE2_PAT( 0, 1, 0, 3, 3, 0 ),
[13] = XE2_PAT( 0, 0, 0, 0, 0, 0 ),
[14] = XE2_PAT( 0, 1, 0, 0, 0, 0 ),
[15] = XE2_PAT( 1, 1, 0, 1, 1, 0 ),
/* 16..19 are reserved; leave set to all 0's */
[20] = XE2_PAT( 0, 0, 1, 0, 3, 0 ),
[21] = XE2_PAT( 0, 1, 1, 0, 3, 0 ),
[22] = XE2_PAT( 0, 0, 1, 0, 3, 2 ),
[23] = XE2_PAT( 0, 0, 1, 0, 3, 3 ),
[24] = XE2_PAT( 0, 0, 2, 0, 3, 0 ),
[25] = XE2_PAT( 0, 1, 2, 0, 3, 0 ),
[26] = XE2_PAT( 0, 0, 2, 0, 3, 2 ),
[27] = XE2_PAT( 0, 0, 2, 0, 3, 3 ),
[28] = XE2_PAT( 0, 0, 3, 0, 3, 0 ),
[29] = XE2_PAT( 0, 1, 3, 0, 3, 0 ),
[30] = XE2_PAT( 0, 0, 3, 0, 3, 2 ),
[31] = XE2_PAT( 0, 0, 3, 0, 3, 3 ),
};
/* Special PAT values programmed outside the main table */
#define XE2_PAT_ATS XE2_PAT( 0, 0, 0, 0, 3, 3 )
static void program_pat(struct xe_gt *gt, const u32 table[], int n_entries)
{
for (int i = 0; i < n_entries; i++) {
......@@ -102,9 +168,33 @@ static const struct xe_pat_ops xelpg_pat_ops = {
.program_media = program_pat_mcr,
};
static void xe2lpg_program_pat(struct xe_gt *gt, const u32 table[], int n_entries)
{
program_pat_mcr(gt, table, n_entries);
xe_gt_mcr_multicast_write(gt, XE_REG_MCR(_PAT_ATS), XE2_PAT_ATS);
}
static void xe2lpm_program_pat(struct xe_gt *gt, const u32 table[], int n_entries)
{
program_pat(gt, table, n_entries);
xe_mmio_write32(gt, XE_REG(_PAT_ATS), XE2_PAT_ATS);
}
static const struct xe_pat_ops xe2_pat_ops = {
.program_graphics = xe2lpg_program_pat,
.program_media = xe2lpm_program_pat,
};
void xe_pat_init_early(struct xe_device *xe)
{
if (xe->info.platform == XE_METEORLAKE) {
if (GRAPHICS_VER(xe) == 20) {
xe->pat.ops = &xe2_pat_ops;
xe->pat.table = xe2_pat_table;
xe->pat.n_entries = ARRAY_SIZE(xe2_pat_table);
xe->pat.idx[XE_CACHE_NONE] = 3;
xe->pat.idx[XE_CACHE_WT] = 15;
xe->pat.idx[XE_CACHE_WB] = 2;
} else if (xe->info.platform == XE_METEORLAKE) {
xe->pat.ops = &xelpg_pat_ops;
xe->pat.table = xelpg_pat_table;
xe->pat.n_entries = ARRAY_SIZE(xelpg_pat_table);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment