Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2020 Intel Corporation
  4 */
  5
  6#include <linux/string_helpers.h>
  7
  8#include "i915_drv.h"
  9#include "i915_reg.h"
 10#include "intel_dram.h"
 11#include "intel_mchbar_regs.h"
 12#include "intel_pcode.h"
 13
 14struct dram_dimm_info {
 15	u16 size;
 16	u8 width, ranks;
 17};
 18
 19struct dram_channel_info {
 20	struct dram_dimm_info dimm_l, dimm_s;
 21	u8 ranks;
 22	bool is_16gb_dimm;
 23};
 24
 25#define DRAM_TYPE_STR(type) [INTEL_DRAM_ ## type] = #type
 26
 27static const char *intel_dram_type_str(enum intel_dram_type type)
 28{
 29	static const char * const str[] = {
 30		DRAM_TYPE_STR(UNKNOWN),
 31		DRAM_TYPE_STR(DDR3),
 32		DRAM_TYPE_STR(DDR4),
 33		DRAM_TYPE_STR(LPDDR3),
 34		DRAM_TYPE_STR(LPDDR4),
 35	};
 36
 37	if (type >= ARRAY_SIZE(str))
 38		type = INTEL_DRAM_UNKNOWN;
 39
 40	return str[type];
 41}
 42
 43#undef DRAM_TYPE_STR
 44
 45static int intel_dimm_num_devices(const struct dram_dimm_info *dimm)
 46{
 47	return dimm->ranks * 64 / (dimm->width ?: 1);
 48}
 49
 50/* Returns total Gb for the whole DIMM */
 51static int skl_get_dimm_size(u16 val)
 52{
 53	return (val & SKL_DRAM_SIZE_MASK) * 8;
 54}
 55
 56static int skl_get_dimm_width(u16 val)
 57{
 58	if (skl_get_dimm_size(val) == 0)
 59		return 0;
 60
 61	switch (val & SKL_DRAM_WIDTH_MASK) {
 62	case SKL_DRAM_WIDTH_X8:
 63	case SKL_DRAM_WIDTH_X16:
 64	case SKL_DRAM_WIDTH_X32:
 65		val = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT;
 66		return 8 << val;
 67	default:
 68		MISSING_CASE(val);
 69		return 0;
 70	}
 71}
 72
 73static int skl_get_dimm_ranks(u16 val)
 74{
 75	if (skl_get_dimm_size(val) == 0)
 76		return 0;
 77
 78	val = (val & SKL_DRAM_RANK_MASK) >> SKL_DRAM_RANK_SHIFT;
 79
 80	return val + 1;
 81}
 82
 83/* Returns total Gb for the whole DIMM */
 84static int icl_get_dimm_size(u16 val)
 85{
 86	return (val & ICL_DRAM_SIZE_MASK) * 8 / 2;
 87}
 88
 89static int icl_get_dimm_width(u16 val)
 90{
 91	if (icl_get_dimm_size(val) == 0)
 92		return 0;
 93
 94	switch (val & ICL_DRAM_WIDTH_MASK) {
 95	case ICL_DRAM_WIDTH_X8:
 96	case ICL_DRAM_WIDTH_X16:
 97	case ICL_DRAM_WIDTH_X32:
 98		val = (val & ICL_DRAM_WIDTH_MASK) >> ICL_DRAM_WIDTH_SHIFT;
 99		return 8 << val;
100	default:
101		MISSING_CASE(val);
102		return 0;
103	}
104}
105
106static int icl_get_dimm_ranks(u16 val)
107{
108	if (icl_get_dimm_size(val) == 0)
109		return 0;
110
111	val = (val & ICL_DRAM_RANK_MASK) >> ICL_DRAM_RANK_SHIFT;
112
113	return val + 1;
114}
115
116static bool
117skl_is_16gb_dimm(const struct dram_dimm_info *dimm)
118{
119	/* Convert total Gb to Gb per DRAM device */
120	return dimm->size / (intel_dimm_num_devices(dimm) ?: 1) == 16;
121}
122
123static void
124skl_dram_get_dimm_info(struct drm_i915_private *i915,
125		       struct dram_dimm_info *dimm,
126		       int channel, char dimm_name, u16 val)
127{
128	if (GRAPHICS_VER(i915) >= 11) {
129		dimm->size = icl_get_dimm_size(val);
130		dimm->width = icl_get_dimm_width(val);
131		dimm->ranks = icl_get_dimm_ranks(val);
132	} else {
133		dimm->size = skl_get_dimm_size(val);
134		dimm->width = skl_get_dimm_width(val);
135		dimm->ranks = skl_get_dimm_ranks(val);
136	}
137
138	drm_dbg_kms(&i915->drm,
139		    "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb DIMMs: %s\n",
140		    channel, dimm_name, dimm->size, dimm->width, dimm->ranks,
141		    str_yes_no(skl_is_16gb_dimm(dimm)));
142}
143
144static int
145skl_dram_get_channel_info(struct drm_i915_private *i915,
146			  struct dram_channel_info *ch,
147			  int channel, u32 val)
148{
149	skl_dram_get_dimm_info(i915, &ch->dimm_l,
150			       channel, 'L', val & 0xffff);
151	skl_dram_get_dimm_info(i915, &ch->dimm_s,
152			       channel, 'S', val >> 16);
153
154	if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) {
155		drm_dbg_kms(&i915->drm, "CH%u not populated\n", channel);
156		return -EINVAL;
157	}
158
159	if (ch->dimm_l.ranks == 2 || ch->dimm_s.ranks == 2)
160		ch->ranks = 2;
161	else if (ch->dimm_l.ranks == 1 && ch->dimm_s.ranks == 1)
162		ch->ranks = 2;
163	else
164		ch->ranks = 1;
165
166	ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) ||
167		skl_is_16gb_dimm(&ch->dimm_s);
168
169	drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb DIMMs: %s\n",
170		    channel, ch->ranks, str_yes_no(ch->is_16gb_dimm));
171
172	return 0;
173}
174
175static bool
176intel_is_dram_symmetric(const struct dram_channel_info *ch0,
177			const struct dram_channel_info *ch1)
178{
179	return !memcmp(ch0, ch1, sizeof(*ch0)) &&
180		(ch0->dimm_s.size == 0 ||
181		 !memcmp(&ch0->dimm_l, &ch0->dimm_s, sizeof(ch0->dimm_l)));
182}
183
184static int
185skl_dram_get_channels_info(struct drm_i915_private *i915)
186{
187	struct dram_info *dram_info = &i915->dram_info;
188	struct dram_channel_info ch0 = {}, ch1 = {};
189	u32 val;
190	int ret;
191
192	val = intel_uncore_read(&i915->uncore,
193				SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
194	ret = skl_dram_get_channel_info(i915, &ch0, 0, val);
195	if (ret == 0)
196		dram_info->num_channels++;
197
198	val = intel_uncore_read(&i915->uncore,
199				SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN);
200	ret = skl_dram_get_channel_info(i915, &ch1, 1, val);
201	if (ret == 0)
202		dram_info->num_channels++;
203
204	if (dram_info->num_channels == 0) {
205		drm_info(&i915->drm, "Number of memory channels is zero\n");
206		return -EINVAL;
207	}
208
209	if (ch0.ranks == 0 && ch1.ranks == 0) {
210		drm_info(&i915->drm, "couldn't get memory rank information\n");
211		return -EINVAL;
212	}
213
214	dram_info->wm_lv_0_adjust_needed = ch0.is_16gb_dimm || ch1.is_16gb_dimm;
215
216	dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1);
217
218	drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n",
219		    str_yes_no(dram_info->symmetric_memory));
220
221	return 0;
222}
223
224static enum intel_dram_type
225skl_get_dram_type(struct drm_i915_private *i915)
226{
227	u32 val;
228
229	val = intel_uncore_read(&i915->uncore,
230				SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN);
231
232	switch (val & SKL_DRAM_DDR_TYPE_MASK) {
233	case SKL_DRAM_DDR_TYPE_DDR3:
234		return INTEL_DRAM_DDR3;
235	case SKL_DRAM_DDR_TYPE_DDR4:
236		return INTEL_DRAM_DDR4;
237	case SKL_DRAM_DDR_TYPE_LPDDR3:
238		return INTEL_DRAM_LPDDR3;
239	case SKL_DRAM_DDR_TYPE_LPDDR4:
240		return INTEL_DRAM_LPDDR4;
241	default:
242		MISSING_CASE(val);
243		return INTEL_DRAM_UNKNOWN;
244	}
245}
246
247static int
248skl_get_dram_info(struct drm_i915_private *i915)
249{
250	struct dram_info *dram_info = &i915->dram_info;
251	int ret;
252
253	dram_info->type = skl_get_dram_type(i915);
254	drm_dbg_kms(&i915->drm, "DRAM type: %s\n",
255		    intel_dram_type_str(dram_info->type));
256
257	ret = skl_dram_get_channels_info(i915);
258	if (ret)
259		return ret;
260
261	return 0;
262}
263
264/* Returns Gb per DRAM device */
265static int bxt_get_dimm_size(u32 val)
266{
267	switch (val & BXT_DRAM_SIZE_MASK) {
268	case BXT_DRAM_SIZE_4GBIT:
269		return 4;
270	case BXT_DRAM_SIZE_6GBIT:
271		return 6;
272	case BXT_DRAM_SIZE_8GBIT:
273		return 8;
274	case BXT_DRAM_SIZE_12GBIT:
275		return 12;
276	case BXT_DRAM_SIZE_16GBIT:
277		return 16;
278	default:
279		MISSING_CASE(val);
280		return 0;
281	}
282}
283
284static int bxt_get_dimm_width(u32 val)
285{
286	if (!bxt_get_dimm_size(val))
287		return 0;
288
289	val = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT;
290
291	return 8 << val;
292}
293
294static int bxt_get_dimm_ranks(u32 val)
295{
296	if (!bxt_get_dimm_size(val))
297		return 0;
298
299	switch (val & BXT_DRAM_RANK_MASK) {
300	case BXT_DRAM_RANK_SINGLE:
301		return 1;
302	case BXT_DRAM_RANK_DUAL:
303		return 2;
304	default:
305		MISSING_CASE(val);
306		return 0;
307	}
308}
309
310static enum intel_dram_type bxt_get_dimm_type(u32 val)
311{
312	if (!bxt_get_dimm_size(val))
313		return INTEL_DRAM_UNKNOWN;
314
315	switch (val & BXT_DRAM_TYPE_MASK) {
316	case BXT_DRAM_TYPE_DDR3:
317		return INTEL_DRAM_DDR3;
318	case BXT_DRAM_TYPE_LPDDR3:
319		return INTEL_DRAM_LPDDR3;
320	case BXT_DRAM_TYPE_DDR4:
321		return INTEL_DRAM_DDR4;
322	case BXT_DRAM_TYPE_LPDDR4:
323		return INTEL_DRAM_LPDDR4;
324	default:
325		MISSING_CASE(val);
326		return INTEL_DRAM_UNKNOWN;
327	}
328}
329
330static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val)
331{
332	dimm->width = bxt_get_dimm_width(val);
333	dimm->ranks = bxt_get_dimm_ranks(val);
334
335	/*
336	 * Size in register is Gb per DRAM device. Convert to total
337	 * Gb to match the way we report this for non-LP platforms.
338	 */
339	dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm);
340}
341
342static int bxt_get_dram_info(struct drm_i915_private *i915)
343{
344	struct dram_info *dram_info = &i915->dram_info;
345	u32 val;
346	u8 valid_ranks = 0;
347	int i;
348
349	/*
350	 * Now read each DUNIT8/9/10/11 to check the rank of each dimms.
351	 */
352	for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) {
353		struct dram_dimm_info dimm;
354		enum intel_dram_type type;
355
356		val = intel_uncore_read(&i915->uncore, BXT_D_CR_DRP0_DUNIT(i));
357		if (val == 0xFFFFFFFF)
358			continue;
359
360		dram_info->num_channels++;
361
362		bxt_get_dimm_info(&dimm, val);
363		type = bxt_get_dimm_type(val);
364
365		drm_WARN_ON(&i915->drm, type != INTEL_DRAM_UNKNOWN &&
366			    dram_info->type != INTEL_DRAM_UNKNOWN &&
367			    dram_info->type != type);
368
369		drm_dbg_kms(&i915->drm,
370			    "CH%u DIMM size: %u Gb, width: X%u, ranks: %u, type: %s\n",
371			    i - BXT_D_CR_DRP0_DUNIT_START,
372			    dimm.size, dimm.width, dimm.ranks,
373			    intel_dram_type_str(type));
374
375		if (valid_ranks == 0)
376			valid_ranks = dimm.ranks;
377
378		if (type != INTEL_DRAM_UNKNOWN)
379			dram_info->type = type;
380	}
381
382	if (dram_info->type == INTEL_DRAM_UNKNOWN || valid_ranks == 0) {
383		drm_info(&i915->drm, "couldn't get memory information\n");
384		return -EINVAL;
385	}
386
387	return 0;
388}
389
390static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv)
391{
392	struct dram_info *dram_info = &dev_priv->dram_info;
393	u32 val = 0;
394	int ret;
395
396	ret = snb_pcode_read(&dev_priv->uncore, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
397			     ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL);
398	if (ret)
399		return ret;
400
401	if (GRAPHICS_VER(dev_priv) == 12) {
402		switch (val & 0xf) {
403		case 0:
404			dram_info->type = INTEL_DRAM_DDR4;
405			break;
406		case 1:
407			dram_info->type = INTEL_DRAM_DDR5;
408			break;
409		case 2:
410			dram_info->type = INTEL_DRAM_LPDDR5;
411			break;
412		case 3:
413			dram_info->type = INTEL_DRAM_LPDDR4;
414			break;
415		case 4:
416			dram_info->type = INTEL_DRAM_DDR3;
417			break;
418		case 5:
419			dram_info->type = INTEL_DRAM_LPDDR3;
420			break;
421		default:
422			MISSING_CASE(val & 0xf);
423			return -EINVAL;
424		}
425	} else {
426		switch (val & 0xf) {
427		case 0:
428			dram_info->type = INTEL_DRAM_DDR4;
429			break;
430		case 1:
431			dram_info->type = INTEL_DRAM_DDR3;
432			break;
433		case 2:
434			dram_info->type = INTEL_DRAM_LPDDR3;
435			break;
436		case 3:
437			dram_info->type = INTEL_DRAM_LPDDR4;
438			break;
439		default:
440			MISSING_CASE(val & 0xf);
441			return -EINVAL;
442		}
443	}
444
445	dram_info->num_channels = (val & 0xf0) >> 4;
446	dram_info->num_qgv_points = (val & 0xf00) >> 8;
447	dram_info->num_psf_gv_points = (val & 0x3000) >> 12;
448
449	return 0;
450}
451
452static int gen11_get_dram_info(struct drm_i915_private *i915)
453{
454	int ret = skl_get_dram_info(i915);
455
456	if (ret)
457		return ret;
458
459	return icl_pcode_read_mem_global_info(i915);
460}
461
462static int gen12_get_dram_info(struct drm_i915_private *i915)
463{
464	i915->dram_info.wm_lv_0_adjust_needed = false;
465
466	return icl_pcode_read_mem_global_info(i915);
467}
468
469static int xelpdp_get_dram_info(struct drm_i915_private *i915)
470{
471	u32 val = intel_uncore_read(&i915->uncore, MTL_MEM_SS_INFO_GLOBAL);
472	struct dram_info *dram_info = &i915->dram_info;
473
474	switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) {
475	case 0:
476		dram_info->type = INTEL_DRAM_DDR4;
477		break;
478	case 1:
479		dram_info->type = INTEL_DRAM_DDR5;
480		break;
481	case 2:
482		dram_info->type = INTEL_DRAM_LPDDR5;
483		break;
484	case 3:
485		dram_info->type = INTEL_DRAM_LPDDR4;
486		break;
487	case 4:
488		dram_info->type = INTEL_DRAM_DDR3;
489		break;
490	case 5:
491		dram_info->type = INTEL_DRAM_LPDDR3;
492		break;
493	default:
494		MISSING_CASE(val);
495		return -EINVAL;
496	}
497
498	dram_info->num_channels = REG_FIELD_GET(MTL_N_OF_POPULATED_CH_MASK, val);
499	dram_info->num_qgv_points = REG_FIELD_GET(MTL_N_OF_ENABLED_QGV_POINTS_MASK, val);
500	/* PSF GV points not supported in D14+ */
501
502	return 0;
503}
504
505void intel_dram_detect(struct drm_i915_private *i915)
506{
507	struct dram_info *dram_info = &i915->dram_info;
508	int ret;
509
510	if (GRAPHICS_VER(i915) < 9 || IS_DG2(i915) || !HAS_DISPLAY(i915))
511		return;
512
513	/*
514	 * Assume level 0 watermark latency adjustment is needed until proven
515	 * otherwise, this w/a is not needed by bxt/glk.
516	 */
517	dram_info->wm_lv_0_adjust_needed = !IS_GEN9_LP(i915);
518
519	if (DISPLAY_VER(i915) >= 14)
520		ret = xelpdp_get_dram_info(i915);
521	else if (GRAPHICS_VER(i915) >= 12)
522		ret = gen12_get_dram_info(i915);
523	else if (GRAPHICS_VER(i915) >= 11)
524		ret = gen11_get_dram_info(i915);
525	else if (IS_GEN9_LP(i915))
526		ret = bxt_get_dram_info(i915);
527	else
528		ret = skl_get_dram_info(i915);
529	if (ret)
530		return;
531
532	drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels);
533
534	drm_dbg_kms(&i915->drm, "Watermark level 0 adjustment needed: %s\n",
535		    str_yes_no(dram_info->wm_lv_0_adjust_needed));
536}
537
538static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap)
539{
540	static const u8 ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 };
541	static const u8 sets[4] = { 1, 1, 2, 2 };
542
543	return EDRAM_NUM_BANKS(cap) *
544		ways[EDRAM_WAYS_IDX(cap)] *
545		sets[EDRAM_SETS_IDX(cap)];
546}
547
548void intel_dram_edram_detect(struct drm_i915_private *i915)
549{
550	u32 edram_cap = 0;
551
552	if (!(IS_HASWELL(i915) || IS_BROADWELL(i915) || GRAPHICS_VER(i915) >= 9))
553		return;
554
555	edram_cap = __raw_uncore_read32(&i915->uncore, HSW_EDRAM_CAP);
556
557	/* NB: We can't write IDICR yet because we don't have gt funcs set up */
558
559	if (!(edram_cap & EDRAM_ENABLED))
560		return;
561
562	/*
563	 * The needed capability bits for size calculation are not there with
564	 * pre gen9 so return 128MB always.
565	 */
566	if (GRAPHICS_VER(i915) < 9)
567		i915->edram_size_mb = 128;
568	else
569		i915->edram_size_mb = gen9_edram_size_mb(i915, edram_cap);
570
571	drm_info(&i915->drm, "Found %uMB of eDRAM\n", i915->edram_size_mb);
572}