summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/soc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/soc')
-rw-r--r--drivers/gpu/drm/i915/soc/intel_dram.c243
-rw-r--r--drivers/gpu/drm/i915/soc/intel_dram.h1
-rw-r--r--drivers/gpu/drm/i915/soc/intel_gmch.c2
-rw-r--r--drivers/gpu/drm/i915/soc/intel_pch.c287
-rw-r--r--drivers/gpu/drm/i915/soc/intel_pch.h89
-rw-r--r--drivers/gpu/drm/i915/soc/intel_rom.c160
-rw-r--r--drivers/gpu/drm/i915/soc/intel_rom.h25
7 files changed, 339 insertions, 468 deletions
diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c
index 15492b69f698..eee5c4f45a43 100644
--- a/drivers/gpu/drm/i915/soc/intel_dram.c
+++ b/drivers/gpu/drm/i915/soc/intel_dram.c
@@ -33,8 +33,14 @@ static const char *intel_dram_type_str(enum intel_dram_type type)
DRAM_TYPE_STR(DDR4),
DRAM_TYPE_STR(LPDDR3),
DRAM_TYPE_STR(LPDDR4),
+ DRAM_TYPE_STR(DDR5),
+ DRAM_TYPE_STR(LPDDR5),
+ DRAM_TYPE_STR(GDDR),
+ DRAM_TYPE_STR(GDDR_ECC),
};
+ BUILD_BUG_ON(ARRAY_SIZE(str) != __INTEL_DRAM_TYPE_MAX);
+
if (type >= ARRAY_SIZE(str))
type = INTEL_DRAM_UNKNOWN;
@@ -43,101 +49,51 @@ static const char *intel_dram_type_str(enum intel_dram_type type)
#undef DRAM_TYPE_STR
-static void pnv_detect_mem_freq(struct drm_i915_private *dev_priv)
+static bool pnv_is_ddr3(struct drm_i915_private *i915)
+{
+ return intel_uncore_read(&i915->uncore, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3;
+}
+
+static unsigned int pnv_mem_freq(struct drm_i915_private *dev_priv)
{
u32 tmp;
tmp = intel_uncore_read(&dev_priv->uncore, CLKCFG);
- switch (tmp & CLKCFG_FSB_MASK) {
- case CLKCFG_FSB_533:
- dev_priv->fsb_freq = 533; /* 133*4 */
- break;
- case CLKCFG_FSB_800:
- dev_priv->fsb_freq = 800; /* 200*4 */
- break;
- case CLKCFG_FSB_667:
- dev_priv->fsb_freq = 667; /* 167*4 */
- break;
- case CLKCFG_FSB_400:
- dev_priv->fsb_freq = 400; /* 100*4 */
- break;
- }
-
switch (tmp & CLKCFG_MEM_MASK) {
case CLKCFG_MEM_533:
- dev_priv->mem_freq = 533;
- break;
+ return 533333;
case CLKCFG_MEM_667:
- dev_priv->mem_freq = 667;
- break;
+ return 666667;
case CLKCFG_MEM_800:
- dev_priv->mem_freq = 800;
- break;
+ return 800000;
}
- /* detect pineview DDR3 setting */
- tmp = intel_uncore_read(&dev_priv->uncore, CSHRDDR3CTL);
- dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0;
+ return 0;
}
-static void ilk_detect_mem_freq(struct drm_i915_private *dev_priv)
+static unsigned int ilk_mem_freq(struct drm_i915_private *dev_priv)
{
- u16 ddrpll, csipll;
+ u16 ddrpll;
ddrpll = intel_uncore_read16(&dev_priv->uncore, DDRMPLL1);
switch (ddrpll & 0xff) {
case 0xc:
- dev_priv->mem_freq = 800;
- break;
+ return 800000;
case 0x10:
- dev_priv->mem_freq = 1066;
- break;
+ return 1066667;
case 0x14:
- dev_priv->mem_freq = 1333;
- break;
+ return 1333333;
case 0x18:
- dev_priv->mem_freq = 1600;
- break;
+ return 1600000;
default:
drm_dbg(&dev_priv->drm, "unknown memory frequency 0x%02x\n",
ddrpll & 0xff);
- dev_priv->mem_freq = 0;
- break;
- }
-
- csipll = intel_uncore_read16(&dev_priv->uncore, CSIPLL0);
- switch (csipll & 0x3ff) {
- case 0x00c:
- dev_priv->fsb_freq = 3200;
- break;
- case 0x00e:
- dev_priv->fsb_freq = 3733;
- break;
- case 0x010:
- dev_priv->fsb_freq = 4266;
- break;
- case 0x012:
- dev_priv->fsb_freq = 4800;
- break;
- case 0x014:
- dev_priv->fsb_freq = 5333;
- break;
- case 0x016:
- dev_priv->fsb_freq = 5866;
- break;
- case 0x018:
- dev_priv->fsb_freq = 6400;
- break;
- default:
- drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n",
- csipll & 0x3ff);
- dev_priv->fsb_freq = 0;
- break;
+ return 0;
}
}
-static void chv_detect_mem_freq(struct drm_i915_private *i915)
+static unsigned int chv_mem_freq(struct drm_i915_private *i915)
{
u32 val;
@@ -147,15 +103,13 @@ static void chv_detect_mem_freq(struct drm_i915_private *i915)
switch ((val >> 2) & 0x7) {
case 3:
- i915->mem_freq = 2000;
- break;
+ return 2000000;
default:
- i915->mem_freq = 1600;
- break;
+ return 1600000;
}
}
-static void vlv_detect_mem_freq(struct drm_i915_private *i915)
+static unsigned int vlv_mem_freq(struct drm_i915_private *i915)
{
u32 val;
@@ -166,30 +120,125 @@ static void vlv_detect_mem_freq(struct drm_i915_private *i915)
switch ((val >> 6) & 3) {
case 0:
case 1:
- i915->mem_freq = 800;
- break;
+ return 800000;
case 2:
- i915->mem_freq = 1066;
- break;
+ return 1066667;
case 3:
- i915->mem_freq = 1333;
- break;
+ return 1333333;
}
+
+ return 0;
}
static void detect_mem_freq(struct drm_i915_private *i915)
{
if (IS_PINEVIEW(i915))
- pnv_detect_mem_freq(i915);
+ i915->mem_freq = pnv_mem_freq(i915);
else if (GRAPHICS_VER(i915) == 5)
- ilk_detect_mem_freq(i915);
+ i915->mem_freq = ilk_mem_freq(i915);
else if (IS_CHERRYVIEW(i915))
- chv_detect_mem_freq(i915);
+ i915->mem_freq = chv_mem_freq(i915);
else if (IS_VALLEYVIEW(i915))
- vlv_detect_mem_freq(i915);
+ i915->mem_freq = vlv_mem_freq(i915);
+
+ if (IS_PINEVIEW(i915))
+ i915->is_ddr3 = pnv_is_ddr3(i915);
if (i915->mem_freq)
- drm_dbg(&i915->drm, "DDR speed: %d MHz\n", i915->mem_freq);
+ drm_dbg(&i915->drm, "DDR speed: %d kHz\n", i915->mem_freq);
+}
+
+unsigned int i9xx_fsb_freq(struct drm_i915_private *i915)
+{
+ u32 fsb;
+
+ /*
+ * Note that this only reads the state of the FSB
+ * straps, not the actual FSB frequency. Some BIOSen
+ * let you configure each independently. Ideally we'd
+ * read out the actual FSB frequency but sadly we
+ * don't know which registers have that information,
+ * and all the relevant docs have gone to bit heaven :(
+ */
+ fsb = intel_uncore_read(&i915->uncore, CLKCFG) & CLKCFG_FSB_MASK;
+
+ if (IS_PINEVIEW(i915) || IS_MOBILE(i915)) {
+ switch (fsb) {
+ case CLKCFG_FSB_400:
+ return 400000;
+ case CLKCFG_FSB_533:
+ return 533333;
+ case CLKCFG_FSB_667:
+ return 666667;
+ case CLKCFG_FSB_800:
+ return 800000;
+ case CLKCFG_FSB_1067:
+ return 1066667;
+ case CLKCFG_FSB_1333:
+ return 1333333;
+ default:
+ MISSING_CASE(fsb);
+ return 1333333;
+ }
+ } else {
+ switch (fsb) {
+ case CLKCFG_FSB_400_ALT:
+ return 400000;
+ case CLKCFG_FSB_533:
+ return 533333;
+ case CLKCFG_FSB_667:
+ return 666667;
+ case CLKCFG_FSB_800:
+ return 800000;
+ case CLKCFG_FSB_1067_ALT:
+ return 1066667;
+ case CLKCFG_FSB_1333_ALT:
+ return 1333333;
+ case CLKCFG_FSB_1600_ALT:
+ return 1600000;
+ default:
+ MISSING_CASE(fsb);
+ return 1333333;
+ }
+ }
+}
+
+static unsigned int ilk_fsb_freq(struct drm_i915_private *dev_priv)
+{
+ u16 fsb;
+
+ fsb = intel_uncore_read16(&dev_priv->uncore, CSIPLL0) & 0x3ff;
+
+ switch (fsb) {
+ case 0x00c:
+ return 3200000;
+ case 0x00e:
+ return 3733333;
+ case 0x010:
+ return 4266667;
+ case 0x012:
+ return 4800000;
+ case 0x014:
+ return 5333333;
+ case 0x016:
+ return 5866667;
+ case 0x018:
+ return 6400000;
+ default:
+ drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n", fsb);
+ return 0;
+ }
+}
+
+static void detect_fsb_freq(struct drm_i915_private *i915)
+{
+ if (GRAPHICS_VER(i915) == 5)
+ i915->fsb_freq = ilk_fsb_freq(i915);
+ else if (GRAPHICS_VER(i915) == 3 || GRAPHICS_VER(i915) == 4)
+ i915->fsb_freq = i9xx_fsb_freq(i915);
+
+ if (i915->fsb_freq)
+ drm_dbg(&i915->drm, "FSB frequency: %d kHz\n", i915->fsb_freq);
}
static int intel_dimm_num_devices(const struct dram_dimm_info *dimm)
@@ -401,8 +450,6 @@ skl_get_dram_info(struct drm_i915_private *i915)
int ret;
dram_info->type = skl_get_dram_type(i915);
- drm_dbg_kms(&i915->drm, "DRAM type: %s\n",
- intel_dram_type_str(dram_info->type));
ret = skl_dram_get_channels_info(i915);
if (ret)
@@ -517,10 +564,9 @@ static int bxt_get_dram_info(struct drm_i915_private *i915)
dram_info->type != type);
drm_dbg_kms(&i915->drm,
- "CH%u DIMM size: %u Gb, width: X%u, ranks: %u, type: %s\n",
+ "CH%u DIMM size: %u Gb, width: X%u, ranks: %u\n",
i - BXT_D_CR_DRP0_DUNIT_START,
- dimm.size, dimm.width, dimm.ranks,
- intel_dram_type_str(type));
+ dimm.size, dimm.width, dimm.ranks);
if (valid_ranks == 0)
valid_ranks = dimm.ranks;
@@ -640,6 +686,14 @@ static int xelpdp_get_dram_info(struct drm_i915_private *i915)
case 5:
dram_info->type = INTEL_DRAM_LPDDR3;
break;
+ case 8:
+ drm_WARN_ON(&i915->drm, !IS_DGFX(i915));
+ dram_info->type = INTEL_DRAM_GDDR;
+ break;
+ case 9:
+ drm_WARN_ON(&i915->drm, !IS_DGFX(i915));
+ dram_info->type = INTEL_DRAM_GDDR_ECC;
+ break;
default:
MISSING_CASE(val);
return -EINVAL;
@@ -657,6 +711,7 @@ void intel_dram_detect(struct drm_i915_private *i915)
struct dram_info *dram_info = &i915->dram_info;
int ret;
+ detect_fsb_freq(i915);
detect_mem_freq(i915);
if (GRAPHICS_VER(i915) < 9 || IS_DG2(i915) || !HAS_DISPLAY(i915))
@@ -666,7 +721,7 @@ void intel_dram_detect(struct drm_i915_private *i915)
* Assume level 0 watermark latency adjustment is needed until proven
* otherwise, this w/a is not needed by bxt/glk.
*/
- dram_info->wm_lv_0_adjust_needed = !IS_GEN9_LP(i915);
+ dram_info->wm_lv_0_adjust_needed = !IS_BROXTON(i915) && !IS_GEMINILAKE(i915);
if (DISPLAY_VER(i915) >= 14)
ret = xelpdp_get_dram_info(i915);
@@ -674,13 +729,19 @@ void intel_dram_detect(struct drm_i915_private *i915)
ret = gen12_get_dram_info(i915);
else if (GRAPHICS_VER(i915) >= 11)
ret = gen11_get_dram_info(i915);
- else if (IS_GEN9_LP(i915))
+ else if (IS_BROXTON(i915) || IS_GEMINILAKE(i915))
ret = bxt_get_dram_info(i915);
else
ret = skl_get_dram_info(i915);
+
+ drm_dbg_kms(&i915->drm, "DRAM type: %s\n",
+ intel_dram_type_str(dram_info->type));
+
if (ret)
return;
+ drm_dbg_kms(&i915->drm, "Num qgv points %u\n", dram_info->num_qgv_points);
+
drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels);
drm_dbg_kms(&i915->drm, "Watermark level 0 adjustment needed: %s\n",
diff --git a/drivers/gpu/drm/i915/soc/intel_dram.h b/drivers/gpu/drm/i915/soc/intel_dram.h
index 4ba13c13162c..a10136eda674 100644
--- a/drivers/gpu/drm/i915/soc/intel_dram.h
+++ b/drivers/gpu/drm/i915/soc/intel_dram.h
@@ -10,5 +10,6 @@ struct drm_i915_private;
void intel_dram_edram_detect(struct drm_i915_private *i915);
void intel_dram_detect(struct drm_i915_private *i915);
+unsigned int i9xx_fsb_freq(struct drm_i915_private *i915);
#endif /* __INTEL_DRAM_H__ */
diff --git a/drivers/gpu/drm/i915/soc/intel_gmch.c b/drivers/gpu/drm/i915/soc/intel_gmch.c
index 40874ebfb64c..734e9f2801ea 100644
--- a/drivers/gpu/drm/i915/soc/intel_gmch.c
+++ b/drivers/gpu/drm/i915/soc/intel_gmch.c
@@ -8,7 +8,7 @@
#include <linux/vgaarb.h>
#include <drm/drm_managed.h>
-#include <drm/i915_drm.h>
+#include <drm/intel/i915_drm.h>
#include "i915_drv.h"
#include "intel_gmch.h"
diff --git a/drivers/gpu/drm/i915/soc/intel_pch.c b/drivers/gpu/drm/i915/soc/intel_pch.c
deleted file mode 100644
index 3cad6dac06b0..000000000000
--- a/drivers/gpu/drm/i915/soc/intel_pch.c
+++ /dev/null
@@ -1,287 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright 2019 Intel Corporation.
- */
-
-#include "i915_drv.h"
-#include "i915_utils.h"
-#include "intel_pch.h"
-
-/* Map PCH device id to PCH type, or PCH_NONE if unknown. */
-static enum intel_pch
-intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
-{
- switch (id) {
- case INTEL_PCH_IBX_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Ibex Peak PCH\n");
- drm_WARN_ON(&dev_priv->drm, GRAPHICS_VER(dev_priv) != 5);
- return PCH_IBX;
- case INTEL_PCH_CPT_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found CougarPoint PCH\n");
- drm_WARN_ON(&dev_priv->drm,
- GRAPHICS_VER(dev_priv) != 6 && !IS_IVYBRIDGE(dev_priv));
- return PCH_CPT;
- case INTEL_PCH_PPT_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found PantherPoint PCH\n");
- drm_WARN_ON(&dev_priv->drm,
- GRAPHICS_VER(dev_priv) != 6 && !IS_IVYBRIDGE(dev_priv));
- /* PPT is CPT compatible */
- return PCH_CPT;
- case INTEL_PCH_LPT_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found LynxPoint PCH\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv));
- drm_WARN_ON(&dev_priv->drm,
- IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv));
- return PCH_LPT;
- case INTEL_PCH_LPT_LP_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found LynxPoint LP PCH\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv));
- drm_WARN_ON(&dev_priv->drm,
- !IS_HASWELL_ULT(dev_priv) && !IS_BROADWELL_ULT(dev_priv));
- return PCH_LPT;
- case INTEL_PCH_WPT_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint PCH\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv));
- drm_WARN_ON(&dev_priv->drm,
- IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv));
- /* WPT is LPT compatible */
- return PCH_LPT;
- case INTEL_PCH_WPT_LP_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found WildcatPoint LP PCH\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv));
- drm_WARN_ON(&dev_priv->drm,
- !IS_HASWELL_ULT(dev_priv) && !IS_BROADWELL_ULT(dev_priv));
- /* WPT is LPT compatible */
- return PCH_LPT;
- case INTEL_PCH_SPT_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint PCH\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv));
- return PCH_SPT;
- case INTEL_PCH_SPT_LP_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found SunrisePoint LP PCH\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_SKYLAKE(dev_priv) &&
- !IS_KABYLAKE(dev_priv) &&
- !IS_COFFEELAKE(dev_priv) &&
- !IS_COMETLAKE(dev_priv));
- return PCH_SPT;
- case INTEL_PCH_KBP_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Kaby Lake PCH (KBP)\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_SKYLAKE(dev_priv) &&
- !IS_KABYLAKE(dev_priv) &&
- !IS_COFFEELAKE(dev_priv) &&
- !IS_COMETLAKE(dev_priv));
- /* KBP is SPT compatible */
- return PCH_SPT;
- case INTEL_PCH_CNP_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Cannon Lake PCH (CNP)\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_COFFEELAKE(dev_priv) &&
- !IS_COMETLAKE(dev_priv));
- return PCH_CNP;
- case INTEL_PCH_CNP_LP_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm,
- "Found Cannon Lake LP PCH (CNP-LP)\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_COFFEELAKE(dev_priv) &&
- !IS_COMETLAKE(dev_priv));
- return PCH_CNP;
- case INTEL_PCH_CMP_DEVICE_ID_TYPE:
- case INTEL_PCH_CMP2_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Comet Lake PCH (CMP)\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_COFFEELAKE(dev_priv) &&
- !IS_COMETLAKE(dev_priv) &&
- !IS_ROCKETLAKE(dev_priv));
- /* CMP is CNP compatible */
- return PCH_CNP;
- case INTEL_PCH_CMP_V_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Comet Lake V PCH (CMP-V)\n");
- drm_WARN_ON(&dev_priv->drm,
- !IS_COFFEELAKE(dev_priv) &&
- !IS_COMETLAKE(dev_priv));
- /* CMP-V is based on KBP, which is SPT compatible */
- return PCH_SPT;
- case INTEL_PCH_ICP_DEVICE_ID_TYPE:
- case INTEL_PCH_ICP2_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n");
- drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv));
- return PCH_ICP;
- case INTEL_PCH_MCC_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Mule Creek Canyon PCH\n");
- drm_WARN_ON(&dev_priv->drm, !(IS_JASPERLAKE(dev_priv) ||
- IS_ELKHARTLAKE(dev_priv)));
- /* MCC is TGP compatible */
- return PCH_TGP;
- case INTEL_PCH_TGP_DEVICE_ID_TYPE:
- case INTEL_PCH_TGP2_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Tiger Lake LP PCH\n");
- drm_WARN_ON(&dev_priv->drm, !IS_TIGERLAKE(dev_priv) &&
- !IS_ROCKETLAKE(dev_priv) &&
- !IS_GEN9_BC(dev_priv));
- return PCH_TGP;
- case INTEL_PCH_JSP_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n");
- drm_WARN_ON(&dev_priv->drm, !(IS_JASPERLAKE(dev_priv) ||
- IS_ELKHARTLAKE(dev_priv)));
- /* JSP is ICP compatible */
- return PCH_ICP;
- case INTEL_PCH_ADP_DEVICE_ID_TYPE:
- case INTEL_PCH_ADP2_DEVICE_ID_TYPE:
- case INTEL_PCH_ADP3_DEVICE_ID_TYPE:
- case INTEL_PCH_ADP4_DEVICE_ID_TYPE:
- drm_dbg_kms(&dev_priv->drm, "Found Alder Lake PCH\n");
- drm_WARN_ON(&dev_priv->drm, !IS_ALDERLAKE_S(dev_priv) &&
- !IS_ALDERLAKE_P(dev_priv));
- return PCH_ADP;
- default:
- return PCH_NONE;
- }
-}
-
-static bool intel_is_virt_pch(unsigned short id,
- unsigned short svendor, unsigned short sdevice)
-{
- return (id == INTEL_PCH_P2X_DEVICE_ID_TYPE ||
- id == INTEL_PCH_P3X_DEVICE_ID_TYPE ||
- (id == INTEL_PCH_QEMU_DEVICE_ID_TYPE &&
- svendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
- sdevice == PCI_SUBDEVICE_ID_QEMU));
-}
-
-static void
-intel_virt_detect_pch(const struct drm_i915_private *dev_priv,
- unsigned short *pch_id, enum intel_pch *pch_type)
-{
- unsigned short id = 0;
-
- /*
- * In a virtualized passthrough environment we can be in a
- * setup where the ISA bridge is not able to be passed through.
- * In this case, a south bridge can be emulated and we have to
- * make an educated guess as to which PCH is really there.
- */
-
- if (IS_ALDERLAKE_S(dev_priv) || IS_ALDERLAKE_P(dev_priv))
- id = INTEL_PCH_ADP_DEVICE_ID_TYPE;
- else if (IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv))
- id = INTEL_PCH_TGP_DEVICE_ID_TYPE;
- else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv))
- id = INTEL_PCH_MCC_DEVICE_ID_TYPE;
- else if (IS_ICELAKE(dev_priv))
- id = INTEL_PCH_ICP_DEVICE_ID_TYPE;
- else if (IS_COFFEELAKE(dev_priv) ||
- IS_COMETLAKE(dev_priv))
- id = INTEL_PCH_CNP_DEVICE_ID_TYPE;
- else if (IS_KABYLAKE(dev_priv) || IS_SKYLAKE(dev_priv))
- id = INTEL_PCH_SPT_DEVICE_ID_TYPE;
- else if (IS_HASWELL_ULT(dev_priv) || IS_BROADWELL_ULT(dev_priv))
- id = INTEL_PCH_LPT_LP_DEVICE_ID_TYPE;
- else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
- id = INTEL_PCH_LPT_DEVICE_ID_TYPE;
- else if (GRAPHICS_VER(dev_priv) == 6 || IS_IVYBRIDGE(dev_priv))
- id = INTEL_PCH_CPT_DEVICE_ID_TYPE;
- else if (GRAPHICS_VER(dev_priv) == 5)
- id = INTEL_PCH_IBX_DEVICE_ID_TYPE;
-
- if (id)
- drm_dbg_kms(&dev_priv->drm, "Assuming PCH ID %04x\n", id);
- else
- drm_dbg_kms(&dev_priv->drm, "Assuming no PCH\n");
-
- *pch_type = intel_pch_type(dev_priv, id);
-
- /* Sanity check virtual PCH id */
- if (drm_WARN_ON(&dev_priv->drm,
- id && *pch_type == PCH_NONE))
- id = 0;
-
- *pch_id = id;
-}
-
-void intel_detect_pch(struct drm_i915_private *dev_priv)
-{
- struct pci_dev *pch = NULL;
- unsigned short id;
- enum intel_pch pch_type;
-
- /*
- * South display engine on the same PCI device: just assign the fake
- * PCH.
- */
- if (DISPLAY_VER(dev_priv) >= 20) {
- dev_priv->pch_type = PCH_LNL;
- return;
- } else if (IS_METEORLAKE(dev_priv)) {
- /*
- * Both north display and south display are on the SoC die.
- * The real PCH is uninvolved in display.
- */
- dev_priv->pch_type = PCH_MTL;
- return;
- } else if (IS_DG2(dev_priv)) {
- dev_priv->pch_type = PCH_DG2;
- return;
- } else if (IS_DG1(dev_priv)) {
- dev_priv->pch_type = PCH_DG1;
- return;
- }
-
- /*
- * The reason to probe ISA bridge instead of Dev31:Fun0 is to
- * make graphics device passthrough work easy for VMM, that only
- * need to expose ISA bridge to let driver know the real hardware
- * underneath. This is a requirement from virtualization team.
- *
- * In some virtualized environments (e.g. XEN), there is irrelevant
- * ISA bridge in the system. To work reliably, we should scan trhough
- * all the ISA bridge devices and check for the first match, instead
- * of only checking the first one.
- */
- while ((pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, pch))) {
- if (pch->vendor != PCI_VENDOR_ID_INTEL)
- continue;
-
- id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
-
- pch_type = intel_pch_type(dev_priv, id);
- if (pch_type != PCH_NONE) {
- dev_priv->pch_type = pch_type;
- dev_priv->pch_id = id;
- break;
- } else if (intel_is_virt_pch(id, pch->subsystem_vendor,
- pch->subsystem_device)) {
- intel_virt_detect_pch(dev_priv, &id, &pch_type);
- dev_priv->pch_type = pch_type;
- dev_priv->pch_id = id;
- break;
- }
- }
-
- /*
- * Use PCH_NOP (PCH but no South Display) for PCH platforms without
- * display.
- */
- if (pch && !HAS_DISPLAY(dev_priv)) {
- drm_dbg_kms(&dev_priv->drm,
- "Display disabled, reverting to NOP PCH\n");
- dev_priv->pch_type = PCH_NOP;
- dev_priv->pch_id = 0;
- } else if (!pch) {
- if (i915_run_as_guest() && HAS_DISPLAY(dev_priv)) {
- intel_virt_detect_pch(dev_priv, &id, &pch_type);
- dev_priv->pch_type = pch_type;
- dev_priv->pch_id = id;
- } else {
- drm_dbg_kms(&dev_priv->drm, "No PCH found.\n");
- }
- }
-
- pci_dev_put(pch);
-}
diff --git a/drivers/gpu/drm/i915/soc/intel_pch.h b/drivers/gpu/drm/i915/soc/intel_pch.h
deleted file mode 100644
index 89e89ede265d..000000000000
--- a/drivers/gpu/drm/i915/soc/intel_pch.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright 2019 Intel Corporation.
- */
-
-#ifndef __INTEL_PCH__
-#define __INTEL_PCH__
-
-struct drm_i915_private;
-
-/*
- * Sorted by south display engine compatibility.
- * If the new PCH comes with a south display engine that is not
- * inherited from the latest item, please do not add it to the
- * end. Instead, add it right after its "parent" PCH.
- */
-enum intel_pch {
- PCH_NOP = -1, /* PCH without south display */
- PCH_NONE = 0, /* No PCH present */
- PCH_IBX, /* Ibexpeak PCH */
- PCH_CPT, /* Cougarpoint/Pantherpoint PCH */
- PCH_LPT, /* Lynxpoint/Wildcatpoint PCH */
- PCH_SPT, /* Sunrisepoint/Kaby Lake PCH */
- PCH_CNP, /* Cannon/Comet Lake PCH */
- PCH_ICP, /* Ice Lake/Jasper Lake PCH */
- PCH_TGP, /* Tiger Lake/Mule Creek Canyon PCH */
- PCH_ADP, /* Alder Lake PCH */
-
- /* Fake PCHs, functionality handled on the same PCI dev */
- PCH_DG1 = 1024,
- PCH_DG2,
- PCH_MTL,
- PCH_LNL,
-};
-
-#define INTEL_PCH_DEVICE_ID_MASK 0xff80
-#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
-#define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00
-#define INTEL_PCH_PPT_DEVICE_ID_TYPE 0x1e00
-#define INTEL_PCH_LPT_DEVICE_ID_TYPE 0x8c00
-#define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE 0x9c00
-#define INTEL_PCH_WPT_DEVICE_ID_TYPE 0x8c80
-#define INTEL_PCH_WPT_LP_DEVICE_ID_TYPE 0x9c80
-#define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100
-#define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00
-#define INTEL_PCH_KBP_DEVICE_ID_TYPE 0xA280
-#define INTEL_PCH_CNP_DEVICE_ID_TYPE 0xA300
-#define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE 0x9D80
-#define INTEL_PCH_CMP_DEVICE_ID_TYPE 0x0280
-#define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680
-#define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380
-#define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480
-#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880
-#define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00
-#define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080
-#define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380
-#define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80
-#define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80
-#define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180
-#define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00
-#define INTEL_PCH_ADP4_DEVICE_ID_TYPE 0x5480
-#define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100
-#define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000
-#define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */
-
-#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type)
-#define INTEL_PCH_ID(dev_priv) ((dev_priv)->pch_id)
-#define HAS_PCH_DG2(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG2)
-#define HAS_PCH_ADP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ADP)
-#define HAS_PCH_DG1(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_DG1)
-#define HAS_PCH_TGP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_TGP)
-#define HAS_PCH_ICP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_ICP)
-#define HAS_PCH_CNP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CNP)
-#define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT)
-#define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT)
-#define HAS_PCH_LPT_LP(dev_priv) \
- (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \
- INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE)
-#define HAS_PCH_LPT_H(dev_priv) \
- (INTEL_PCH_ID(dev_priv) == INTEL_PCH_LPT_DEVICE_ID_TYPE || \
- INTEL_PCH_ID(dev_priv) == INTEL_PCH_WPT_DEVICE_ID_TYPE)
-#define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT)
-#define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX)
-#define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP)
-#define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE)
-
-void intel_detect_pch(struct drm_i915_private *dev_priv);
-
-#endif /* __INTEL_PCH__ */
diff --git a/drivers/gpu/drm/i915/soc/intel_rom.c b/drivers/gpu/drm/i915/soc/intel_rom.c
new file mode 100644
index 000000000000..243d98cab8c3
--- /dev/null
+++ b/drivers/gpu/drm/i915/soc/intel_rom.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "i915_reg.h"
+
+#include "intel_rom.h"
+#include "intel_uncore.h"
+
+struct intel_rom {
+ /* for PCI ROM */
+ struct pci_dev *pdev;
+ void __iomem *oprom;
+
+ /* for SPI */
+ struct intel_uncore *uncore;
+ loff_t offset;
+
+ size_t size;
+
+ u32 (*read32)(struct intel_rom *rom, loff_t offset);
+ u16 (*read16)(struct intel_rom *rom, loff_t offset);
+ void (*read_block)(struct intel_rom *rom, void *data, loff_t offset, size_t size);
+ void (*free)(struct intel_rom *rom);
+};
+
+static u32 spi_read32(struct intel_rom *rom, loff_t offset)
+{
+ intel_uncore_write(rom->uncore, PRIMARY_SPI_ADDRESS,
+ rom->offset + offset);
+
+ return intel_uncore_read(rom->uncore, PRIMARY_SPI_TRIGGER);
+}
+
+static u16 spi_read16(struct intel_rom *rom, loff_t offset)
+{
+ return spi_read32(rom, offset) & 0xffff;
+}
+
+struct intel_rom *intel_rom_spi(struct drm_i915_private *i915)
+{
+ struct intel_rom *rom;
+ u32 static_region;
+
+ rom = kzalloc(sizeof(*rom), GFP_KERNEL);
+ if (!rom)
+ return NULL;
+
+ rom->uncore = &i915->uncore;
+
+ static_region = intel_uncore_read(rom->uncore, SPI_STATIC_REGIONS);
+ static_region &= OPTIONROM_SPI_REGIONID_MASK;
+ intel_uncore_write(rom->uncore, PRIMARY_SPI_REGIONID, static_region);
+
+ rom->offset = intel_uncore_read(rom->uncore, OROM_OFFSET) & OROM_OFFSET_MASK;
+
+ rom->size = 0x200000;
+
+ rom->read32 = spi_read32;
+ rom->read16 = spi_read16;
+
+ return rom;
+}
+
+static u32 pci_read32(struct intel_rom *rom, loff_t offset)
+{
+ return ioread32(rom->oprom + offset);
+}
+
+static u16 pci_read16(struct intel_rom *rom, loff_t offset)
+{
+ return ioread16(rom->oprom + offset);
+}
+
+static void pci_read_block(struct intel_rom *rom, void *data,
+ loff_t offset, size_t size)
+{
+ memcpy_fromio(data, rom->oprom + offset, size);
+}
+
+static void pci_free(struct intel_rom *rom)
+{
+ pci_unmap_rom(rom->pdev, rom->oprom);
+}
+
+struct intel_rom *intel_rom_pci(struct drm_i915_private *i915)
+{
+ struct intel_rom *rom;
+
+ rom = kzalloc(sizeof(*rom), GFP_KERNEL);
+ if (!rom)
+ return NULL;
+
+ rom->pdev = to_pci_dev(i915->drm.dev);
+
+ rom->oprom = pci_map_rom(rom->pdev, &rom->size);
+ if (!rom->oprom) {
+ kfree(rom);
+ return NULL;
+ }
+
+ rom->read32 = pci_read32;
+ rom->read16 = pci_read16;
+ rom->read_block = pci_read_block;
+ rom->free = pci_free;
+
+ return rom;
+}
+
+u32 intel_rom_read32(struct intel_rom *rom, loff_t offset)
+{
+ return rom->read32(rom, offset);
+}
+
+u16 intel_rom_read16(struct intel_rom *rom, loff_t offset)
+{
+ return rom->read16(rom, offset);
+}
+
+void intel_rom_read_block(struct intel_rom *rom, void *data,
+ loff_t offset, size_t size)
+{
+ u32 *ptr = data;
+ loff_t index;
+
+ if (rom->read_block) {
+ rom->read_block(rom, data, offset, size);
+ return;
+ }
+
+ for (index = 0; index < size; index += 4)
+ *ptr++ = rom->read32(rom, offset + index);
+}
+
+loff_t intel_rom_find(struct intel_rom *rom, u32 needle)
+{
+ loff_t offset;
+
+ for (offset = 0; offset < rom->size; offset += 4) {
+ if (rom->read32(rom, offset) == needle)
+ return offset;
+ }
+
+ return -ENOENT;
+}
+
+size_t intel_rom_size(struct intel_rom *rom)
+{
+ return rom->size;
+}
+
+void intel_rom_free(struct intel_rom *rom)
+{
+ if (rom && rom->free)
+ rom->free(rom);
+
+ kfree(rom);
+}
diff --git a/drivers/gpu/drm/i915/soc/intel_rom.h b/drivers/gpu/drm/i915/soc/intel_rom.h
new file mode 100644
index 000000000000..fb2979c8ef7f
--- /dev/null
+++ b/drivers/gpu/drm/i915/soc/intel_rom.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#ifndef __INTEL_ROM_H__
+#define __INTEL_ROM_H__
+
+#include <linux/types.h>
+
+struct drm_i915_private;
+struct intel_rom;
+
+struct intel_rom *intel_rom_spi(struct drm_i915_private *i915);
+struct intel_rom *intel_rom_pci(struct drm_i915_private *i915);
+
+u32 intel_rom_read32(struct intel_rom *rom, loff_t offset);
+u16 intel_rom_read16(struct intel_rom *rom, loff_t offset);
+void intel_rom_read_block(struct intel_rom *rom, void *data,
+ loff_t offset, size_t size);
+loff_t intel_rom_find(struct intel_rom *rom, u32 needle);
+size_t intel_rom_size(struct intel_rom *rom);
+void intel_rom_free(struct intel_rom *rom);
+
+#endif /* __INTEL_ROM_H__ */