intel_gvt_sanitize_options(dev_priv);
}
+static int
+bxt_get_dram_info(struct drm_i915_private *dev_priv)
+{
+ struct dram_info *dram_info = &dev_priv->dram_info;
+ u32 dram_channels;
+ u32 mem_freq_khz, val;
+ u8 num_active_channels;
+ int i;
+
+ val = I915_READ(BXT_P_CR_MC_BIOS_REQ_0_0_0);
+ mem_freq_khz = DIV_ROUND_UP((val & BXT_REQ_DATA_MASK) *
+ BXT_MEMORY_FREQ_MULTIPLIER_HZ, 1000);
+
+ dram_channels = val & BXT_DRAM_CHANNEL_ACTIVE_MASK;
+ num_active_channels = hweight32(dram_channels);
+
+ /* Each active bit represents 4-byte channel */
+ dram_info->bandwidth_kbps = (mem_freq_khz * num_active_channels * 4);
+
+ if (dram_info->bandwidth_kbps == 0) {
+ DRM_INFO("Couldn't get system memory bandwidth\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Now read each DUNIT8/9/10/11 to check the rank of each dimms.
+ */
+ for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) {
+ u8 size, width;
+ enum dram_rank rank;
+ u32 tmp;
+
+ val = I915_READ(BXT_D_CR_DRP0_DUNIT(i));
+ if (val == 0xFFFFFFFF)
+ continue;
+
+ dram_info->num_channels++;
+ tmp = val & BXT_DRAM_RANK_MASK;
+
+ if (tmp == BXT_DRAM_RANK_SINGLE)
+ rank = I915_DRAM_RANK_SINGLE;
+ else if (tmp == BXT_DRAM_RANK_DUAL)
+ rank = I915_DRAM_RANK_DUAL;
+ else
+ rank = I915_DRAM_RANK_INVALID;
+
+ tmp = val & BXT_DRAM_SIZE_MASK;
+ if (tmp == BXT_DRAM_SIZE_4GB)
+ size = 4;
+ else if (tmp == BXT_DRAM_SIZE_6GB)
+ size = 6;
+ else if (tmp == BXT_DRAM_SIZE_8GB)
+ size = 8;
+ else if (tmp == BXT_DRAM_SIZE_12GB)
+ size = 12;
+ else if (tmp == BXT_DRAM_SIZE_16GB)
+ size = 16;
+ else
+ size = 0;
+
+ tmp = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT;
+ width = (1 << tmp) * 8;
+ DRM_DEBUG_KMS("dram size:%dGB width:X%d rank:%s\n", size,
+ width, rank == I915_DRAM_RANK_SINGLE ? "single" :
+ rank == I915_DRAM_RANK_DUAL ? "dual" : "unknown");
+
+ /*
+ * If any of the channel is single rank channel,
+ * worst case output will be same as if single rank
+ * memory, so consider single rank memory.
+ */
+ if (dram_info->rank == I915_DRAM_RANK_INVALID)
+ dram_info->rank = rank;
+ else if (rank == I915_DRAM_RANK_SINGLE)
+ dram_info->rank = I915_DRAM_RANK_SINGLE;
+ }
+
+ if (dram_info->rank == I915_DRAM_RANK_INVALID) {
+ DRM_INFO("couldn't get memory rank information\n");
+ return -EINVAL;
+ }
+
+ dram_info->valid = true;
+ return 0;
+}
+
+static void
+intel_get_dram_info(struct drm_i915_private *dev_priv)
+{
+ struct dram_info *dram_info = &dev_priv->dram_info;
+ int ret;
+
+ dram_info->valid = false;
+ dram_info->rank = I915_DRAM_RANK_INVALID;
+ dram_info->bandwidth_kbps = 0;
+ dram_info->num_channels = 0;
+
+ if (!IS_BROXTON(dev_priv))
+ return;
+
+ ret = bxt_get_dram_info(dev_priv);
+ if (ret)
+ return;
+
+ DRM_DEBUG_KMS("DRAM bandwidth:%d KBps, total-channels: %u\n",
+ dram_info->bandwidth_kbps, dram_info->num_channels);
+ DRM_DEBUG_KMS("DRAM rank: %s rank\n",
+ (dram_info->rank == I915_DRAM_RANK_DUAL) ?
+ "dual" : "single");
+}
+
/**
* i915_driver_init_hw - setup state requiring device access
* @dev_priv: device private
goto err_msi;
intel_opregion_setup(dev_priv);
+ /*
+ * Fill the dram structure to get the system raw bandwidth and
+ * dram info. This will be used for memory latency calculation.
+ */
+ intel_get_dram_info(dev_priv);
+
return 0;
#define DC_STATE_DEBUG_MASK_CORES (1 << 0)
#define DC_STATE_DEBUG_MASK_MEMORY_UP (1 << 1)
+#define BXT_P_CR_MC_BIOS_REQ_0_0_0 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x7114)
+#define BXT_REQ_DATA_MASK 0x3F
+#define BXT_DRAM_CHANNEL_ACTIVE_SHIFT 12
+#define BXT_DRAM_CHANNEL_ACTIVE_MASK (0xF << 12)
+#define BXT_MEMORY_FREQ_MULTIPLIER_HZ 133333333
+
+#define BXT_D_CR_DRP0_DUNIT8 0x1000
+#define BXT_D_CR_DRP0_DUNIT9 0x1200
+#define BXT_D_CR_DRP0_DUNIT_START 8
+#define BXT_D_CR_DRP0_DUNIT_END 11
+#define BXT_D_CR_DRP0_DUNIT(x) _MMIO(MCHBAR_MIRROR_BASE_SNB + \
+ _PICK_EVEN((x) - 8, BXT_D_CR_DRP0_DUNIT8,\
+ BXT_D_CR_DRP0_DUNIT9))
+#define BXT_DRAM_RANK_MASK 0x3
+#define BXT_DRAM_RANK_SINGLE 0x1
+#define BXT_DRAM_RANK_DUAL 0x3
+#define BXT_DRAM_WIDTH_MASK (0x3 << 4)
+#define BXT_DRAM_WIDTH_SHIFT 4
+#define BXT_DRAM_WIDTH_X8 (0x0 << 4)
+#define BXT_DRAM_WIDTH_X16 (0x1 << 4)
+#define BXT_DRAM_WIDTH_X32 (0x2 << 4)
+#define BXT_DRAM_WIDTH_X64 (0x3 << 4)
+#define BXT_DRAM_SIZE_MASK (0x7 << 6)
+#define BXT_DRAM_SIZE_SHIFT 6
+#define BXT_DRAM_SIZE_4GB (0x0 << 6)
+#define BXT_DRAM_SIZE_6GB (0x1 << 6)
+#define BXT_DRAM_SIZE_8GB (0x2 << 6)
+#define BXT_DRAM_SIZE_12GB (0x3 << 6)
+#define BXT_DRAM_SIZE_16GB (0x4 << 6)
+
/* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register,
* since on HSW we can't write to it using I915_WRITE. */
#define D_COMP_HSW _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5F0C)