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