diff options
Diffstat (limited to 'drivers/gpu/drm/i915/soc')
-rw-r--r-- | drivers/gpu/drm/i915/soc/intel_dram.c | 243 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/soc/intel_dram.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/soc/intel_gmch.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/soc/intel_pch.c | 287 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/soc/intel_pch.h | 89 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/soc/intel_rom.c | 160 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/soc/intel_rom.h | 25 |
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__ */ |