blob: 389a91c25aaf9bb6272e36c088c97bb9b3fd0bf1 [file] [log] [blame]
Sean Rhodes2e665eb2021-06-01 22:55:07 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <option.h>
4#include <soc/cnl_memcfg_init.h>
5#include <soc/romstage.h>
6#include <console/console.h>
7#include <gpio.h>
8#include <string.h>
9#include <types.h>
10
11#include "baseboard/memory.h"
12
13u8 get_memory_config_straps(void)
14{
15 /*
16 * The hardware supports a number of different memory configurations
17 * which are selected using four ID bits ID3 (GPP_H7), ID2 (GPP_H6),
18 * ID1 (GPP_E23) and ID0 (GPP_E22).
19 *
20 * The mapping is defined in the schematics as follows ID3 is always
21 * 0 and can be ignored):
22 *
23 * ID2ID1ID0Memory type
24 * --------------------
25 * 1 1 1 Samsung 4G single channel
26 * 1 1 0 Samsung 8G dual channel
27 * 1 0 1 Micron 4G single channel
28 * 1 0 0 Micron 8G dual channel
29 * 0 1 1 Hynix 4G single channel
30 * 0 1 0 Hynix 8G dual channel
31 * 0 0 1 Micron 16G dual channel
32 * 0 0 0 Hynix 16G dual channel
33 *
34 * We return the value of these bits so that the index into the SPD
35 * table can be .spd[] values can be configured correctly in the
36 * memory configuration structure.
37 */
38
39 gpio_t memid_gpios[] = {
40 GPP_E22,
41 GPP_E23,
42 GPP_H6
43 };
44 return (u8)gpio_base2_value(memid_gpios, ARRAY_SIZE(memid_gpios));
45}
46
47const struct cnl_mb_cfg *get_memory_cfg(struct cnl_mb_cfg *mem_cfg)
48{
49 u8 memid;
50
51 struct cnl_mb_cfg std_memcfg = {
52 /*
53 * The dqs_map arrays map the DDR4 pins to the SoC pins
54 * for both channels.
55 *
56 * the index = pin number on DDR4 part
57 * the value = pin number on SoC
58 */
59 .dqs_map[DDR_CH0] = {0, 6, 1, 3, 5, 2, 7, 4},
60 .dqs_map[DDR_CH1] = {7, 5, 3, 6, 2, 4, 0, 1},
61
62 /*
63 * Mainboard uses 121, 81 and 100 rcomp resistors. See R6E1, R6E2
64 * and R6E3 on page 6 of the schematics.
65 */
66 .rcomp_resistor = {121, 81, 100},
67
68 /*
69 * Mainboard Rcomp target values.
70 */
71 .rcomp_targets = {100, 40, 20, 20, 26},
72
73 /*
74 * Mainboard is a non-interleaved design - see pages 5 & 6
75 * of the schematics.
76 */
77 .dq_pins_interleaved = 0,
78
79 /*
80 * Mainboard is using DDR_VREF_CA for CH_A and DDR1_VREF_DQ for
81 * CH_B - see page 5 of the schematics.
82 */
83 .vref_ca_config = 2,
84
85 /* Disable Early Command Training */
86 .ect = 0,
87 };
88
89 memcpy(mem_cfg, &std_memcfg, sizeof(std_memcfg));
90
91 memid = get_memory_config_straps();
92 printk(BIOS_DEBUG, "Memory config straps: 0x%.2x\n", memid);
93
94 /*
95 * If we are using single channel ID = 3, 5 or 7 then we only
96 * populate .spd[0].If we are dual channel then we also populate
97 * .spd[2] as well.
98 */
99 mem_cfg->spd[0].read_type = READ_SPD_CBFS;
100 mem_cfg->spd[0].spd_spec.spd_index = memid;
101 if (memid != 3 && memid != 5 && memid != 7) {
102 mem_cfg->spd[2].read_type = READ_SPD_CBFS;
103 mem_cfg->spd[2].spd_spec.spd_index = memid;
104 }
105
106 return mem_cfg;
107};
108
109void mainboard_memory_init_params(FSPM_UPD *memupd)
110{
111 struct cnl_mb_cfg board_memcfg;
112
113 const uint8_t vtd = get_uint_option("vtd", 1);
114 memupd->FspmTestConfig.VtdDisable = !vtd;
115 const uint8_t ht = get_uint_option("hyper_threading", memupd->FspmConfig.HyperThreading);
116 memupd->FspmConfig.HyperThreading = ht;
117
118 cannonlake_memcfg_init(&memupd->FspmConfig, get_memory_cfg(&board_memcfg));
119}