aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 2ddf8538cb47..44e2c0f5ec50 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1063,6 +1063,300 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv)
1063 intel_gvt_sanitize_options(dev_priv); 1063 intel_gvt_sanitize_options(dev_priv);
1064} 1064}
1065 1065
1066static enum dram_rank skl_get_dimm_rank(u8 size, u32 rank)
1067{
1068 if (size == 0)
1069 return I915_DRAM_RANK_INVALID;
1070 if (rank == SKL_DRAM_RANK_SINGLE)
1071 return I915_DRAM_RANK_SINGLE;
1072 else if (rank == SKL_DRAM_RANK_DUAL)
1073 return I915_DRAM_RANK_DUAL;
1074
1075 return I915_DRAM_RANK_INVALID;
1076}
1077
1078static bool
1079skl_is_16gb_dimm(enum dram_rank rank, u8 size, u8 width)
1080{
1081 if (rank == I915_DRAM_RANK_SINGLE && width == 8 && size == 16)
1082 return true;
1083 else if (rank == I915_DRAM_RANK_DUAL && width == 8 && size == 32)
1084 return true;
1085 else if (rank == SKL_DRAM_RANK_SINGLE && width == 16 && size == 8)
1086 return true;
1087 else if (rank == SKL_DRAM_RANK_DUAL && width == 16 && size == 16)
1088 return true;
1089
1090 return false;
1091}
1092
1093static int
1094skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val)
1095{
1096 u32 tmp_l, tmp_s;
1097 u32 s_val = val >> SKL_DRAM_S_SHIFT;
1098
1099 if (!val)
1100 return -EINVAL;
1101
1102 tmp_l = val & SKL_DRAM_SIZE_MASK;
1103 tmp_s = s_val & SKL_DRAM_SIZE_MASK;
1104
1105 if (tmp_l == 0 && tmp_s == 0)
1106 return -EINVAL;
1107
1108 ch->l_info.size = tmp_l;
1109 ch->s_info.size = tmp_s;
1110
1111 tmp_l = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT;
1112 tmp_s = (s_val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT;
1113 ch->l_info.width = (1 << tmp_l) * 8;
1114 ch->s_info.width = (1 << tmp_s) * 8;
1115
1116 tmp_l = val & SKL_DRAM_RANK_MASK;
1117 tmp_s = s_val & SKL_DRAM_RANK_MASK;
1118 ch->l_info.rank = skl_get_dimm_rank(ch->l_info.size, tmp_l);
1119 ch->s_info.rank = skl_get_dimm_rank(ch->s_info.size, tmp_s);
1120
1121 if (ch->l_info.rank == I915_DRAM_RANK_DUAL ||
1122 ch->s_info.rank == I915_DRAM_RANK_DUAL)
1123 ch->rank = I915_DRAM_RANK_DUAL;
1124 else if (ch->l_info.rank == I915_DRAM_RANK_SINGLE &&
1125 ch->s_info.rank == I915_DRAM_RANK_SINGLE)
1126 ch->rank = I915_DRAM_RANK_DUAL;
1127 else
1128 ch->rank = I915_DRAM_RANK_SINGLE;
1129
1130 ch->is_16gb_dimm = skl_is_16gb_dimm(ch->l_info.rank, ch->l_info.size,
1131 ch->l_info.width) ||
1132 skl_is_16gb_dimm(ch->s_info.rank, ch->s_info.size,
1133 ch->s_info.width);
1134
1135 DRM_DEBUG_KMS("(size:width:rank) L(%dGB:X%d:%s) S(%dGB:X%d:%s)\n",
1136 ch->l_info.size, ch->l_info.width,
1137 ch->l_info.rank ? "dual" : "single",
1138 ch->s_info.size, ch->s_info.width,
1139 ch->s_info.rank ? "dual" : "single");
1140
1141 return 0;
1142}
1143
1144static bool
1145intel_is_dram_symmetric(u32 val_ch0, u32 val_ch1,
1146 struct dram_channel_info *ch0)
1147{
1148 return (val_ch0 == val_ch1 &&
1149 (ch0->s_info.size == 0 ||
1150 (ch0->l_info.size == ch0->s_info.size &&
1151 ch0->l_info.width == ch0->s_info.width &&
1152 ch0->l_info.rank == ch0->s_info.rank)));
1153}
1154
1155static int
1156skl_dram_get_channels_info(struct drm_i915_private *dev_priv)
1157{
1158 struct dram_info *dram_info = &dev_priv->dram_info;
1159 struct dram_channel_info ch0, ch1;
1160 u32 val_ch0, val_ch1;
1161 int ret;
1162
1163 val_ch0 = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
1164 ret = skl_dram_get_channel_info(&ch0, val_ch0);
1165 if (ret == 0)
1166 dram_info->num_channels++;
1167
1168 val_ch1 = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN);
1169 ret = skl_dram_get_channel_info(&ch1, val_ch1);
1170 if (ret == 0)
1171 dram_info->num_channels++;
1172
1173 if (dram_info->num_channels == 0) {
1174 DRM_INFO("Number of memory channels is zero\n");
1175 return -EINVAL;
1176 }
1177
1178 dram_info->valid_dimm = true;
1179
1180 /*
1181 * If any of the channel is single rank channel, worst case output
1182 * will be same as if single rank memory, so consider single rank
1183 * memory.
1184 */
1185 if (ch0.rank == I915_DRAM_RANK_SINGLE ||
1186 ch1.rank == I915_DRAM_RANK_SINGLE)
1187 dram_info->rank = I915_DRAM_RANK_SINGLE;
1188 else
1189 dram_info->rank = max(ch0.rank, ch1.rank);
1190
1191 if (dram_info->rank == I915_DRAM_RANK_INVALID) {
1192 DRM_INFO("couldn't get memory rank information\n");
1193 return -EINVAL;
1194 }
1195
1196 if (ch0.is_16gb_dimm || ch1.is_16gb_dimm)
1197 dram_info->is_16gb_dimm = true;
1198
1199 dev_priv->dram_info.symmetric_memory = intel_is_dram_symmetric(val_ch0,
1200 val_ch1,
1201 &ch0);
1202
1203 DRM_DEBUG_KMS("memory configuration is %sSymmetric memory\n",
1204 dev_priv->dram_info.symmetric_memory ? "" : "not ");
1205 return 0;
1206}
1207
1208static int
1209skl_get_dram_info(struct drm_i915_private *dev_priv)
1210{
1211 struct dram_info *dram_info = &dev_priv->dram_info;
1212 u32 mem_freq_khz, val;
1213 int ret;
1214
1215 ret = skl_dram_get_channels_info(dev_priv);
1216 if (ret)
1217 return ret;
1218
1219 val = I915_READ(SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU);
1220 mem_freq_khz = DIV_ROUND_UP((val & SKL_REQ_DATA_MASK) *
1221 SKL_MEMORY_FREQ_MULTIPLIER_HZ, 1000);
1222
1223 dram_info->bandwidth_kbps = dram_info->num_channels *
1224 mem_freq_khz * 8;
1225
1226 if (dram_info->bandwidth_kbps == 0) {
1227 DRM_INFO("Couldn't get system memory bandwidth\n");
1228 return -EINVAL;
1229 }
1230
1231 dram_info->valid = true;
1232 return 0;
1233}
1234
1235static int
1236bxt_get_dram_info(struct drm_i915_private *dev_priv)
1237{
1238 struct dram_info *dram_info = &dev_priv->dram_info;
1239 u32 dram_channels;
1240 u32 mem_freq_khz, val;
1241 u8 num_active_channels;
1242 int i;
1243
1244 val = I915_READ(BXT_P_CR_MC_BIOS_REQ_0_0_0);
1245 mem_freq_khz = DIV_ROUND_UP((val & BXT_REQ_DATA_MASK) *
1246 BXT_MEMORY_FREQ_MULTIPLIER_HZ, 1000);
1247
1248 dram_channels = val & BXT_DRAM_CHANNEL_ACTIVE_MASK;
1249 num_active_channels = hweight32(dram_channels);
1250
1251 /* Each active bit represents 4-byte channel */
1252 dram_info->bandwidth_kbps = (mem_freq_khz * num_active_channels * 4);
1253
1254 if (dram_info->bandwidth_kbps == 0) {
1255 DRM_INFO("Couldn't get system memory bandwidth\n");
1256 return -EINVAL;
1257 }
1258
1259 /*
1260 * Now read each DUNIT8/9/10/11 to check the rank of each dimms.
1261 */
1262 for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) {
1263 u8 size, width;
1264 enum dram_rank rank;
1265 u32 tmp;
1266
1267 val = I915_READ(BXT_D_CR_DRP0_DUNIT(i));
1268 if (val == 0xFFFFFFFF)
1269 continue;
1270
1271 dram_info->num_channels++;
1272 tmp = val & BXT_DRAM_RANK_MASK;
1273
1274 if (tmp == BXT_DRAM_RANK_SINGLE)
1275 rank = I915_DRAM_RANK_SINGLE;
1276 else if (tmp == BXT_DRAM_RANK_DUAL)
1277 rank = I915_DRAM_RANK_DUAL;
1278 else
1279 rank = I915_DRAM_RANK_INVALID;
1280
1281 tmp = val & BXT_DRAM_SIZE_MASK;
1282 if (tmp == BXT_DRAM_SIZE_4GB)
1283 size = 4;
1284 else if (tmp == BXT_DRAM_SIZE_6GB)
1285 size = 6;
1286 else if (tmp == BXT_DRAM_SIZE_8GB)
1287 size = 8;
1288 else if (tmp == BXT_DRAM_SIZE_12GB)
1289 size = 12;
1290 else if (tmp == BXT_DRAM_SIZE_16GB)
1291 size = 16;
1292 else
1293 size = 0;
1294
1295 tmp = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT;
1296 width = (1 << tmp) * 8;
1297 DRM_DEBUG_KMS("dram size:%dGB width:X%d rank:%s\n", size,
1298 width, rank == I915_DRAM_RANK_SINGLE ? "single" :
1299 rank == I915_DRAM_RANK_DUAL ? "dual" : "unknown");
1300
1301 /*
1302 * If any of the channel is single rank channel,
1303 * worst case output will be same as if single rank
1304 * memory, so consider single rank memory.
1305 */
1306 if (dram_info->rank == I915_DRAM_RANK_INVALID)
1307 dram_info->rank = rank;
1308 else if (rank == I915_DRAM_RANK_SINGLE)
1309 dram_info->rank = I915_DRAM_RANK_SINGLE;
1310 }
1311
1312 if (dram_info->rank == I915_DRAM_RANK_INVALID) {
1313 DRM_INFO("couldn't get memory rank information\n");
1314 return -EINVAL;
1315 }
1316
1317 dram_info->valid_dimm = true;
1318 dram_info->valid = true;
1319 return 0;
1320}
1321
1322static void
1323intel_get_dram_info(struct drm_i915_private *dev_priv)
1324{
1325 struct dram_info *dram_info = &dev_priv->dram_info;
1326 char bandwidth_str[32];
1327 int ret;
1328
1329 dram_info->valid = false;
1330 dram_info->valid_dimm = false;
1331 dram_info->is_16gb_dimm = false;
1332 dram_info->rank = I915_DRAM_RANK_INVALID;
1333 dram_info->bandwidth_kbps = 0;
1334 dram_info->num_channels = 0;
1335
1336 if (INTEL_GEN(dev_priv) < 9 || IS_GEMINILAKE(dev_priv))
1337 return;
1338
1339 /* Need to calculate bandwidth only for Gen9 */
1340 if (IS_BROXTON(dev_priv))
1341 ret = bxt_get_dram_info(dev_priv);
1342 else if (INTEL_GEN(dev_priv) == 9)
1343 ret = skl_get_dram_info(dev_priv);
1344 else
1345 ret = skl_dram_get_channels_info(dev_priv);
1346 if (ret)
1347 return;
1348
1349 if (dram_info->bandwidth_kbps)
1350 sprintf(bandwidth_str, "%d KBps", dram_info->bandwidth_kbps);
1351 else
1352 sprintf(bandwidth_str, "unknown");
1353 DRM_DEBUG_KMS("DRAM bandwidth:%s, total-channels: %u\n",
1354 bandwidth_str, dram_info->num_channels);
1355 DRM_DEBUG_KMS("DRAM rank: %s rank 16GB-dimm:%s\n",
1356 (dram_info->rank == I915_DRAM_RANK_DUAL) ?
1357 "dual" : "single", yesno(dram_info->is_16gb_dimm));
1358}
1359
1066/** 1360/**
1067 * i915_driver_init_hw - setup state requiring device access 1361 * i915_driver_init_hw - setup state requiring device access
1068 * @dev_priv: device private 1362 * @dev_priv: device private
@@ -1180,6 +1474,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
1180 goto err_msi; 1474 goto err_msi;
1181 1475
1182 intel_opregion_setup(dev_priv); 1476 intel_opregion_setup(dev_priv);
1477 /*
1478 * Fill the dram structure to get the system raw bandwidth and
1479 * dram info. This will be used for memory latency calculation.
1480 */
1481 intel_get_dram_info(dev_priv);
1482
1183 1483
1184 return 0; 1484 return 0;
1185 1485