xref: /linux/drivers/gpu/drm/i915/display/intel_dram.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2020 Intel Corporation
4  */
5 
6 #include <linux/string_helpers.h>
7 
8 #include <drm/drm_managed.h>
9 #include <drm/drm_print.h>
10 #include <drm/intel/intel_pcode_regs.h>
11 
12 #include "intel_de.h"
13 #include "intel_display_core.h"
14 #include "intel_display_utils.h"
15 #include "intel_display_regs.h"
16 #include "intel_display_wa.h"
17 #include "intel_dram.h"
18 #include "intel_mchbar.h"
19 #include "intel_parent.h"
20 #include "vlv_sideband.h"
21 
22 struct dram_dimm_info {
23 	u16 size;
24 	u8 width, ranks;
25 };
26 
27 struct dram_channel_info {
28 	struct dram_dimm_info dimm_l, dimm_s;
29 	u8 ranks;
30 	bool is_16gb_dimm;
31 };
32 
33 #define DRAM_TYPE_STR(type) [INTEL_DRAM_ ## type] = #type
34 
35 const char *intel_dram_type_str(enum intel_dram_type type)
36 {
37 	static const char * const str[] = {
38 		DRAM_TYPE_STR(UNKNOWN),
39 		DRAM_TYPE_STR(DDR2),
40 		DRAM_TYPE_STR(DDR3),
41 		DRAM_TYPE_STR(DDR4),
42 		DRAM_TYPE_STR(LPDDR3),
43 		DRAM_TYPE_STR(LPDDR4),
44 		DRAM_TYPE_STR(DDR5),
45 		DRAM_TYPE_STR(LPDDR5),
46 		DRAM_TYPE_STR(GDDR),
47 		DRAM_TYPE_STR(GDDR_ECC),
48 	};
49 
50 	BUILD_BUG_ON(ARRAY_SIZE(str) != __INTEL_DRAM_TYPE_MAX);
51 
52 	if (type >= ARRAY_SIZE(str))
53 		type = INTEL_DRAM_UNKNOWN;
54 
55 	return str[type];
56 }
57 
58 #undef DRAM_TYPE_STR
59 
60 static enum intel_dram_type pnv_dram_type(struct intel_display *display)
61 {
62 	return intel_mchbar_read(display, CSHRDDR3CTL) & CSHRDDR3CTL_DDR3 ?
63 		INTEL_DRAM_DDR3 : INTEL_DRAM_DDR2;
64 }
65 
66 static unsigned int pnv_mem_freq(struct intel_display *display)
67 {
68 	u32 tmp;
69 
70 	tmp = intel_mchbar_read(display, CLKCFG);
71 
72 	switch (tmp & CLKCFG_MEM_MASK) {
73 	case CLKCFG_MEM_533:
74 		return 533333;
75 	case CLKCFG_MEM_667:
76 		return 666667;
77 	case CLKCFG_MEM_800:
78 		return 800000;
79 	}
80 
81 	return 0;
82 }
83 
84 static unsigned int ilk_mem_freq(struct intel_display *display)
85 {
86 	u16 ddrpll;
87 
88 	ddrpll = intel_mchbar_read16(display, DDRMPLL1);
89 	switch (ddrpll & 0xff) {
90 	case 0xc:
91 		return 800000;
92 	case 0x10:
93 		return 1066667;
94 	case 0x14:
95 		return 1333333;
96 	case 0x18:
97 		return 1600000;
98 	default:
99 		drm_dbg_kms(display->drm, "unknown memory frequency 0x%02x\n",
100 			    ddrpll & 0xff);
101 		return 0;
102 	}
103 }
104 
105 static unsigned int chv_mem_freq(struct intel_display *display)
106 {
107 	u32 val;
108 
109 	vlv_cck_get(display);
110 	val = vlv_cck_read(display, CCK_FUSE_REG);
111 	vlv_cck_put(display);
112 
113 	switch ((val >> 2) & 0x7) {
114 	case 3:
115 		return 2000000;
116 	default:
117 		return 1600000;
118 	}
119 }
120 
121 static unsigned int vlv_mem_freq(struct intel_display *display)
122 {
123 	u32 val;
124 
125 	vlv_punit_get(display);
126 	val = vlv_punit_read(display, PUNIT_REG_GPU_FREQ_STS);
127 	vlv_punit_put(display);
128 
129 	switch ((val >> 6) & 3) {
130 	case 0:
131 	case 1:
132 		return 800000;
133 	case 2:
134 		return 1066667;
135 	case 3:
136 		return 1333333;
137 	}
138 
139 	return 0;
140 }
141 
142 unsigned int intel_mem_freq(struct intel_display *display)
143 {
144 	if (display->platform.pineview)
145 		return pnv_mem_freq(display);
146 	else if (DISPLAY_VER(display) == 5)
147 		return ilk_mem_freq(display);
148 	else if (display->platform.cherryview)
149 		return chv_mem_freq(display);
150 	else if (display->platform.valleyview)
151 		return vlv_mem_freq(display);
152 	else
153 		return 0;
154 }
155 
156 static unsigned int i9xx_fsb_freq(struct intel_display *display)
157 {
158 	u32 fsb;
159 
160 	/*
161 	 * Note that this only reads the state of the FSB
162 	 * straps, not the actual FSB frequency. Some BIOSen
163 	 * let you configure each independently. Ideally we'd
164 	 * read out the actual FSB frequency but sadly we
165 	 * don't know which registers have that information,
166 	 * and all the relevant docs have gone to bit heaven :(
167 	 */
168 	fsb = intel_mchbar_read(display, CLKCFG) & CLKCFG_FSB_MASK;
169 
170 	if (display->platform.pineview || display->platform.mobile) {
171 		switch (fsb) {
172 		case CLKCFG_FSB_400:
173 			return 400000;
174 		case CLKCFG_FSB_533:
175 			return 533333;
176 		case CLKCFG_FSB_667:
177 			return 666667;
178 		case CLKCFG_FSB_800:
179 			return 800000;
180 		case CLKCFG_FSB_1067:
181 			return 1066667;
182 		case CLKCFG_FSB_1333:
183 			return 1333333;
184 		default:
185 			MISSING_CASE(fsb);
186 			return 1333333;
187 		}
188 	} else {
189 		switch (fsb) {
190 		case CLKCFG_FSB_400_ALT:
191 			return 400000;
192 		case CLKCFG_FSB_533:
193 			return 533333;
194 		case CLKCFG_FSB_667:
195 			return 666667;
196 		case CLKCFG_FSB_800:
197 			return 800000;
198 		case CLKCFG_FSB_1067_ALT:
199 			return 1066667;
200 		case CLKCFG_FSB_1333_ALT:
201 			return 1333333;
202 		case CLKCFG_FSB_1600_ALT:
203 			return 1600000;
204 		default:
205 			MISSING_CASE(fsb);
206 			return 1333333;
207 		}
208 	}
209 }
210 
211 static unsigned int ilk_fsb_freq(struct intel_display *display)
212 {
213 	u16 fsb;
214 
215 	fsb = intel_mchbar_read16(display, CSIPLL0) & 0x3ff;
216 
217 	switch (fsb) {
218 	case 0x00c:
219 		return 3200000;
220 	case 0x00e:
221 		return 3733333;
222 	case 0x010:
223 		return 4266667;
224 	case 0x012:
225 		return 4800000;
226 	case 0x014:
227 		return 5333333;
228 	case 0x016:
229 		return 5866667;
230 	case 0x018:
231 		return 6400000;
232 	default:
233 		drm_dbg_kms(display->drm, "unknown fsb frequency 0x%04x\n", fsb);
234 		return 0;
235 	}
236 }
237 
238 unsigned int intel_fsb_freq(struct intel_display *display)
239 {
240 	if (DISPLAY_VER(display) == 5)
241 		return ilk_fsb_freq(display);
242 	else if (IS_DISPLAY_VER(display, 3, 4))
243 		return i9xx_fsb_freq(display);
244 	else
245 		return 0;
246 }
247 
248 static int i915_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
249 {
250 	dram_info->fsb_freq = intel_fsb_freq(display);
251 	if (dram_info->fsb_freq)
252 		drm_dbg_kms(display->drm, "FSB frequency: %d kHz\n", dram_info->fsb_freq);
253 
254 	dram_info->mem_freq = intel_mem_freq(display);
255 	if (dram_info->mem_freq)
256 		drm_dbg_kms(display->drm, "DDR speed: %d kHz\n", dram_info->mem_freq);
257 
258 	if (display->platform.pineview)
259 		dram_info->type = pnv_dram_type(display);
260 
261 	return 0;
262 }
263 
264 static int intel_dimm_num_devices(const struct dram_dimm_info *dimm)
265 {
266 	return dimm->ranks * 64 / (dimm->width ?: 1);
267 }
268 
269 /* Returns total Gb for the whole DIMM */
270 static int skl_get_dimm_s_size(u32 val)
271 {
272 	return REG_FIELD_GET(SKL_DIMM_S_SIZE_MASK, val) * 8;
273 }
274 
275 static int skl_get_dimm_l_size(u32 val)
276 {
277 	return REG_FIELD_GET(SKL_DIMM_L_SIZE_MASK, val) * 8;
278 }
279 
280 static int skl_get_dimm_s_width(u32 val)
281 {
282 	if (skl_get_dimm_s_size(val) == 0)
283 		return 0;
284 
285 	switch (val & SKL_DIMM_S_WIDTH_MASK) {
286 	case SKL_DIMM_S_WIDTH_X8:
287 	case SKL_DIMM_S_WIDTH_X16:
288 	case SKL_DIMM_S_WIDTH_X32:
289 		return 8 << REG_FIELD_GET(SKL_DIMM_S_WIDTH_MASK, val);
290 	default:
291 		MISSING_CASE(val);
292 		return 0;
293 	}
294 }
295 
296 static int skl_get_dimm_l_width(u32 val)
297 {
298 	if (skl_get_dimm_l_size(val) == 0)
299 		return 0;
300 
301 	switch (val & SKL_DIMM_L_WIDTH_MASK) {
302 	case SKL_DIMM_L_WIDTH_X8:
303 	case SKL_DIMM_L_WIDTH_X16:
304 	case SKL_DIMM_L_WIDTH_X32:
305 		return 8 << REG_FIELD_GET(SKL_DIMM_L_WIDTH_MASK, val);
306 	default:
307 		MISSING_CASE(val);
308 		return 0;
309 	}
310 }
311 
312 static int skl_get_dimm_s_ranks(u32 val)
313 {
314 	if (skl_get_dimm_s_size(val) == 0)
315 		return 0;
316 
317 	return REG_FIELD_GET(SKL_DIMM_S_RANK_MASK, val) + 1;
318 }
319 
320 static int skl_get_dimm_l_ranks(u32 val)
321 {
322 	if (skl_get_dimm_l_size(val) == 0)
323 		return 0;
324 
325 	return REG_FIELD_GET(SKL_DIMM_L_RANK_MASK, val) + 1;
326 }
327 
328 /* Returns total Gb for the whole DIMM */
329 static int icl_get_dimm_s_size(u32 val)
330 {
331 	return REG_FIELD_GET(ICL_DIMM_S_SIZE_MASK, val) * 8 / 2;
332 }
333 
334 static int icl_get_dimm_l_size(u32 val)
335 {
336 	return REG_FIELD_GET(ICL_DIMM_L_SIZE_MASK, val) * 8 / 2;
337 }
338 
339 static int icl_get_dimm_s_width(u32 val)
340 {
341 	if (icl_get_dimm_s_size(val) == 0)
342 		return 0;
343 
344 	switch (val & ICL_DIMM_S_WIDTH_MASK) {
345 	case ICL_DIMM_S_WIDTH_X8:
346 	case ICL_DIMM_S_WIDTH_X16:
347 	case ICL_DIMM_S_WIDTH_X32:
348 		return 8 << REG_FIELD_GET(ICL_DIMM_S_WIDTH_MASK, val);
349 	default:
350 		MISSING_CASE(val);
351 		return 0;
352 	}
353 }
354 
355 static int icl_get_dimm_l_width(u32 val)
356 {
357 	if (icl_get_dimm_l_size(val) == 0)
358 		return 0;
359 
360 	switch (val & ICL_DIMM_L_WIDTH_MASK) {
361 	case ICL_DIMM_L_WIDTH_X8:
362 	case ICL_DIMM_L_WIDTH_X16:
363 	case ICL_DIMM_L_WIDTH_X32:
364 		return 8 << REG_FIELD_GET(ICL_DIMM_L_WIDTH_MASK, val);
365 	default:
366 		MISSING_CASE(val);
367 		return 0;
368 	}
369 }
370 
371 static int icl_get_dimm_s_ranks(u32 val)
372 {
373 	if (icl_get_dimm_s_size(val) == 0)
374 		return 0;
375 
376 	return REG_FIELD_GET(ICL_DIMM_S_RANK_MASK, val) + 1;
377 }
378 
379 static int icl_get_dimm_l_ranks(u32 val)
380 {
381 	if (icl_get_dimm_l_size(val) == 0)
382 		return 0;
383 
384 	return REG_FIELD_GET(ICL_DIMM_L_RANK_MASK, val) + 1;
385 }
386 
387 static bool
388 skl_is_16gb_dimm(const struct dram_dimm_info *dimm)
389 {
390 	/* Convert total Gb to Gb per DRAM device */
391 	return dimm->size / (intel_dimm_num_devices(dimm) ?: 1) >= 16;
392 }
393 
394 static void
395 skl_dram_print_dimm_info(struct intel_display *display,
396 			 struct dram_dimm_info *dimm,
397 			 int channel, char dimm_name)
398 {
399 	drm_dbg_kms(display->drm,
400 		    "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb+ DIMMs: %s\n",
401 		    channel, dimm_name, dimm->size, dimm->width, dimm->ranks,
402 		    str_yes_no(skl_is_16gb_dimm(dimm)));
403 }
404 
405 static void
406 skl_dram_get_dimm_l_info(struct intel_display *display,
407 			 struct dram_dimm_info *dimm,
408 			 int channel, u32 val)
409 {
410 	if (DISPLAY_VER(display) >= 11) {
411 		dimm->size = icl_get_dimm_l_size(val);
412 		dimm->width = icl_get_dimm_l_width(val);
413 		dimm->ranks = icl_get_dimm_l_ranks(val);
414 	} else {
415 		dimm->size = skl_get_dimm_l_size(val);
416 		dimm->width = skl_get_dimm_l_width(val);
417 		dimm->ranks = skl_get_dimm_l_ranks(val);
418 	}
419 
420 	skl_dram_print_dimm_info(display, dimm, channel, 'L');
421 }
422 
423 static void
424 skl_dram_get_dimm_s_info(struct intel_display *display,
425 			 struct dram_dimm_info *dimm,
426 			 int channel, u32 val)
427 {
428 	if (DISPLAY_VER(display) >= 11) {
429 		dimm->size = icl_get_dimm_s_size(val);
430 		dimm->width = icl_get_dimm_s_width(val);
431 		dimm->ranks = icl_get_dimm_s_ranks(val);
432 	} else {
433 		dimm->size = skl_get_dimm_s_size(val);
434 		dimm->width = skl_get_dimm_s_width(val);
435 		dimm->ranks = skl_get_dimm_s_ranks(val);
436 	}
437 
438 	skl_dram_print_dimm_info(display, dimm, channel, 'S');
439 }
440 
441 static int
442 skl_dram_get_channel_info(struct intel_display *display,
443 			  struct dram_channel_info *ch,
444 			  int channel, u32 val)
445 {
446 	skl_dram_get_dimm_l_info(display, &ch->dimm_l, channel, val);
447 	skl_dram_get_dimm_s_info(display, &ch->dimm_s, channel, val);
448 
449 	if (ch->dimm_l.size == 0 && ch->dimm_s.size == 0) {
450 		drm_dbg_kms(display->drm, "CH%u not populated\n", channel);
451 		return -EINVAL;
452 	}
453 
454 	if (ch->dimm_l.ranks == 2 || ch->dimm_s.ranks == 2)
455 		ch->ranks = 2;
456 	else if (ch->dimm_l.ranks == 1 && ch->dimm_s.ranks == 1)
457 		ch->ranks = 2;
458 	else
459 		ch->ranks = 1;
460 
461 	ch->is_16gb_dimm = skl_is_16gb_dimm(&ch->dimm_l) ||
462 		skl_is_16gb_dimm(&ch->dimm_s);
463 
464 	drm_dbg_kms(display->drm, "CH%u ranks: %u, 16Gb+ DIMMs: %s\n",
465 		    channel, ch->ranks, str_yes_no(ch->is_16gb_dimm));
466 
467 	return 0;
468 }
469 
470 static bool
471 intel_is_dram_symmetric(const struct dram_channel_info *ch0,
472 			const struct dram_channel_info *ch1)
473 {
474 	return !memcmp(ch0, ch1, sizeof(*ch0)) &&
475 		(ch0->dimm_s.size == 0 ||
476 		 !memcmp(&ch0->dimm_l, &ch0->dimm_s, sizeof(ch0->dimm_l)));
477 }
478 
479 static int
480 skl_dram_get_channels_info(struct intel_display *display, struct dram_info *dram_info)
481 {
482 	struct dram_channel_info ch0 = {}, ch1 = {};
483 	u32 val;
484 	int ret;
485 
486 	/* Assume 16Gb+ DIMMs are present until proven otherwise */
487 	dram_info->has_16gb_dimms = true;
488 
489 	val = intel_mchbar_read(display, SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN);
490 	ret = skl_dram_get_channel_info(display, &ch0, 0, val);
491 	if (ret == 0)
492 		dram_info->num_channels++;
493 
494 	val = intel_mchbar_read(display, SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN);
495 	ret = skl_dram_get_channel_info(display, &ch1, 1, val);
496 	if (ret == 0)
497 		dram_info->num_channels++;
498 
499 	if (dram_info->num_channels == 0) {
500 		drm_info(display->drm, "Number of memory channels is zero\n");
501 		return -EINVAL;
502 	}
503 
504 	if (ch0.ranks == 0 && ch1.ranks == 0) {
505 		drm_info(display->drm, "couldn't get memory rank information\n");
506 		return -EINVAL;
507 	}
508 
509 	dram_info->has_16gb_dimms = ch0.is_16gb_dimm || ch1.is_16gb_dimm;
510 
511 	dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1);
512 
513 	drm_dbg_kms(display->drm, "Memory configuration is symmetric? %s\n",
514 		    str_yes_no(dram_info->symmetric_memory));
515 
516 	drm_dbg_kms(display->drm, "16Gb+ DIMMs: %s\n",
517 		    str_yes_no(dram_info->has_16gb_dimms));
518 
519 	return 0;
520 }
521 
522 static enum intel_dram_type
523 skl_get_dram_type(struct intel_display *display)
524 {
525 	u32 val;
526 
527 	val = intel_mchbar_read(display, SKL_MAD_INTER_CHANNEL_0_0_0_MCHBAR_MCMAIN);
528 
529 	switch (val & SKL_DRAM_DDR_TYPE_MASK) {
530 	case SKL_DRAM_DDR_TYPE_DDR3:
531 		return INTEL_DRAM_DDR3;
532 	case SKL_DRAM_DDR_TYPE_DDR4:
533 		return INTEL_DRAM_DDR4;
534 	case SKL_DRAM_DDR_TYPE_LPDDR3:
535 		return INTEL_DRAM_LPDDR3;
536 	case SKL_DRAM_DDR_TYPE_LPDDR4:
537 		return INTEL_DRAM_LPDDR4;
538 	default:
539 		MISSING_CASE(val);
540 		return INTEL_DRAM_UNKNOWN;
541 	}
542 }
543 
544 static int
545 skl_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
546 {
547 	int ret;
548 
549 	dram_info->type = skl_get_dram_type(display);
550 
551 	ret = skl_dram_get_channels_info(display, dram_info);
552 	if (ret)
553 		return ret;
554 
555 	return 0;
556 }
557 
558 /* Returns Gb per DRAM device */
559 static int bxt_get_dimm_size(u32 val)
560 {
561 	switch (val & BXT_DRAM_SIZE_MASK) {
562 	case BXT_DRAM_SIZE_4GBIT:
563 		return 4;
564 	case BXT_DRAM_SIZE_6GBIT:
565 		return 6;
566 	case BXT_DRAM_SIZE_8GBIT:
567 		return 8;
568 	case BXT_DRAM_SIZE_12GBIT:
569 		return 12;
570 	case BXT_DRAM_SIZE_16GBIT:
571 		return 16;
572 	default:
573 		MISSING_CASE(val);
574 		return 0;
575 	}
576 }
577 
578 static int bxt_get_dimm_width(u32 val)
579 {
580 	if (!bxt_get_dimm_size(val))
581 		return 0;
582 
583 	val = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT;
584 
585 	return 8 << val;
586 }
587 
588 static int bxt_get_dimm_ranks(u32 val)
589 {
590 	if (!bxt_get_dimm_size(val))
591 		return 0;
592 
593 	switch (val & BXT_DRAM_RANK_MASK) {
594 	case BXT_DRAM_RANK_SINGLE:
595 		return 1;
596 	case BXT_DRAM_RANK_DUAL:
597 		return 2;
598 	default:
599 		MISSING_CASE(val);
600 		return 0;
601 	}
602 }
603 
604 static enum intel_dram_type bxt_get_dimm_type(u32 val)
605 {
606 	if (!bxt_get_dimm_size(val))
607 		return INTEL_DRAM_UNKNOWN;
608 
609 	switch (val & BXT_DRAM_TYPE_MASK) {
610 	case BXT_DRAM_TYPE_DDR3:
611 		return INTEL_DRAM_DDR3;
612 	case BXT_DRAM_TYPE_LPDDR3:
613 		return INTEL_DRAM_LPDDR3;
614 	case BXT_DRAM_TYPE_DDR4:
615 		return INTEL_DRAM_DDR4;
616 	case BXT_DRAM_TYPE_LPDDR4:
617 		return INTEL_DRAM_LPDDR4;
618 	default:
619 		MISSING_CASE(val);
620 		return INTEL_DRAM_UNKNOWN;
621 	}
622 }
623 
624 static void bxt_get_dimm_info(struct dram_dimm_info *dimm, u32 val)
625 {
626 	dimm->width = bxt_get_dimm_width(val);
627 	dimm->ranks = bxt_get_dimm_ranks(val);
628 
629 	/*
630 	 * Size in register is Gb per DRAM device. Convert to total
631 	 * Gb to match the way we report this for non-LP platforms.
632 	 */
633 	dimm->size = bxt_get_dimm_size(val) * intel_dimm_num_devices(dimm);
634 }
635 
636 static int bxt_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
637 {
638 	u32 val;
639 	u8 valid_ranks = 0;
640 	int i;
641 
642 	/*
643 	 * Now read each DUNIT8/9/10/11 to check the rank of each dimms.
644 	 */
645 	for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) {
646 		struct dram_dimm_info dimm;
647 		enum intel_dram_type type;
648 
649 		val = intel_mchbar_read(display, BXT_D_CR_DRP0_DUNIT(i));
650 		if (val == 0xFFFFFFFF)
651 			continue;
652 
653 		dram_info->num_channels++;
654 
655 		bxt_get_dimm_info(&dimm, val);
656 		type = bxt_get_dimm_type(val);
657 
658 		drm_WARN_ON(display->drm, type != INTEL_DRAM_UNKNOWN &&
659 			    dram_info->type != INTEL_DRAM_UNKNOWN &&
660 			    dram_info->type != type);
661 
662 		drm_dbg_kms(display->drm,
663 			    "CH%u DIMM size: %u Gb, width: X%u, ranks: %u\n",
664 			    i - BXT_D_CR_DRP0_DUNIT_START,
665 			    dimm.size, dimm.width, dimm.ranks);
666 
667 		if (valid_ranks == 0)
668 			valid_ranks = dimm.ranks;
669 
670 		if (type != INTEL_DRAM_UNKNOWN)
671 			dram_info->type = type;
672 	}
673 
674 	if (dram_info->type == INTEL_DRAM_UNKNOWN || valid_ranks == 0) {
675 		drm_info(display->drm, "couldn't get memory information\n");
676 		return -EINVAL;
677 	}
678 
679 	return 0;
680 }
681 
682 static int icl_pcode_read_mem_global_info(struct intel_display *display,
683 					  struct dram_info *dram_info)
684 {
685 	u32 val = 0;
686 	int ret;
687 
688 	ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
689 				      ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL);
690 	if (ret)
691 		return ret;
692 
693 	if (DISPLAY_VER(display) >= 12) {
694 		switch (val & 0xf) {
695 		case 0:
696 			dram_info->type = INTEL_DRAM_DDR4;
697 			break;
698 		case 1:
699 			dram_info->type = INTEL_DRAM_DDR5;
700 			break;
701 		case 2:
702 			dram_info->type = INTEL_DRAM_LPDDR5;
703 			break;
704 		case 3:
705 			dram_info->type = INTEL_DRAM_LPDDR4;
706 			break;
707 		case 4:
708 			dram_info->type = INTEL_DRAM_DDR3;
709 			break;
710 		case 5:
711 			dram_info->type = INTEL_DRAM_LPDDR3;
712 			break;
713 		default:
714 			MISSING_CASE(val & 0xf);
715 			return -EINVAL;
716 		}
717 	} else {
718 		switch (val & 0xf) {
719 		case 0:
720 			dram_info->type = INTEL_DRAM_DDR4;
721 			break;
722 		case 1:
723 			dram_info->type = INTEL_DRAM_DDR3;
724 			break;
725 		case 2:
726 			dram_info->type = INTEL_DRAM_LPDDR3;
727 			break;
728 		case 3:
729 			dram_info->type = INTEL_DRAM_LPDDR4;
730 			break;
731 		default:
732 			MISSING_CASE(val & 0xf);
733 			return -EINVAL;
734 		}
735 	}
736 
737 	dram_info->num_channels = (val & 0xf0) >> 4;
738 	dram_info->num_qgv_points = (val & 0xf00) >> 8;
739 	dram_info->num_psf_gv_points = (val & 0x3000) >> 12;
740 
741 	return 0;
742 }
743 
744 static int gen11_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
745 {
746 	int ret;
747 
748 	ret = skl_dram_get_channels_info(display, dram_info);
749 	if (ret)
750 		return ret;
751 
752 	return icl_pcode_read_mem_global_info(display, dram_info);
753 }
754 
755 static int gen12_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
756 {
757 	return icl_pcode_read_mem_global_info(display, dram_info);
758 }
759 
760 static int xelpdp_get_dram_info(struct intel_display *display, struct dram_info *dram_info)
761 {
762 	u32 val = intel_de_read(display, MTL_MEM_SS_INFO_GLOBAL);
763 
764 	switch (REG_FIELD_GET(MTL_DDR_TYPE_MASK, val)) {
765 	case 0:
766 		dram_info->type = INTEL_DRAM_DDR4;
767 		break;
768 	case 1:
769 		dram_info->type = INTEL_DRAM_DDR5;
770 		break;
771 	case 2:
772 		dram_info->type = INTEL_DRAM_LPDDR5;
773 		break;
774 	case 3:
775 		dram_info->type = INTEL_DRAM_LPDDR4;
776 		break;
777 	case 4:
778 		dram_info->type = INTEL_DRAM_DDR3;
779 		break;
780 	case 5:
781 		dram_info->type = INTEL_DRAM_LPDDR3;
782 		break;
783 	case 8:
784 		drm_WARN_ON(display->drm, !display->platform.dgfx);
785 		dram_info->type = INTEL_DRAM_GDDR;
786 		break;
787 	case 9:
788 		drm_WARN_ON(display->drm, !display->platform.dgfx);
789 		dram_info->type = INTEL_DRAM_GDDR_ECC;
790 		break;
791 	default:
792 		MISSING_CASE(val);
793 		return -EINVAL;
794 	}
795 
796 	dram_info->num_channels = REG_FIELD_GET(MTL_N_OF_POPULATED_CH_MASK, val);
797 	dram_info->num_qgv_points = REG_FIELD_GET(MTL_N_OF_ENABLED_QGV_POINTS_MASK, val);
798 
799 	/*
800 	 * Wa_16030862157
801 	 * MEM_SS_INFO_GLOBAL populated-channel field is only 4 bits and
802 	 * cannot encode 16, so on Xe3p the BIOS programs the saturated field
803 	 * value (0xf) to indicate the fully-populated 16-channel config (4
804 	 * memory controllers x 4 channels). Interpret it as 16.
805 	 */
806 
807 	if (intel_display_wa(display, INTEL_DISPLAY_WA_16030862157) &&
808 	    dram_info->num_channels == REG_FIELD_MAX(MTL_N_OF_POPULATED_CH_MASK))
809 		dram_info->num_channels = 16;
810 
811 	if (DISPLAY_VER(display) >= 35)
812 		dram_info->ecc_impacting_de_bw = REG_FIELD_GET(XE3P_ECC_IMPACTING_DE, val);
813 
814 	return 0;
815 }
816 
817 int intel_dram_detect(struct intel_display *display)
818 {
819 	struct dram_info *dram_info;
820 	int ret;
821 
822 	if (display->platform.dg2 || !HAS_DISPLAY(display))
823 		return 0;
824 
825 	dram_info = drmm_kzalloc(display->drm, sizeof(*dram_info), GFP_KERNEL);
826 	if (!dram_info)
827 		return -ENOMEM;
828 
829 	display->dram.info = dram_info;
830 
831 	if (DISPLAY_VER(display) >= 14)
832 		ret = xelpdp_get_dram_info(display, dram_info);
833 	else if (DISPLAY_VER(display) >= 12)
834 		ret = gen12_get_dram_info(display, dram_info);
835 	else if (DISPLAY_VER(display) >= 11)
836 		ret = gen11_get_dram_info(display, dram_info);
837 	else if (display->platform.broxton || display->platform.geminilake)
838 		ret = bxt_get_dram_info(display, dram_info);
839 	else if (DISPLAY_VER(display) >= 9)
840 		ret = skl_get_dram_info(display, dram_info);
841 	else
842 		ret = i915_get_dram_info(display, dram_info);
843 
844 	drm_dbg_kms(display->drm, "DRAM type: %s\n",
845 		    intel_dram_type_str(dram_info->type));
846 
847 	drm_dbg_kms(display->drm, "DRAM channels: %u\n", dram_info->num_channels);
848 
849 	drm_dbg_kms(display->drm, "Num QGV points %u\n", dram_info->num_qgv_points);
850 	drm_dbg_kms(display->drm, "Num PSF GV points %u\n", dram_info->num_psf_gv_points);
851 
852 	/* TODO: Do we want to abort probe on dram detection failures? */
853 	if (ret)
854 		return 0;
855 
856 	return 0;
857 }
858 
859 /*
860  * Returns NULL for platforms that don't have dram info. Avoid overzealous NULL
861  * checks, and prefer not dereferencing on platforms that shouldn't look at dram
862  * info, to catch accidental and incorrect dram info checks.
863  */
864 const struct dram_info *intel_dram_info(struct intel_display *display)
865 {
866 	return display->dram.info;
867 }
868