blob: 2dab8504c4767fdce47e067ca16056dca998764a [file] [log] [blame]
Angel Pons1b254222022-05-07 13:48:53 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include <cbfs.h>
4#include <commonlib/bsd/clamp.h>
5#include <console/console.h>
6#include <device/dram/ddr3.h>
7#include <device/smbus_host.h>
8#include <northbridge/intel/haswell/haswell.h>
9#include <northbridge/intel/haswell/raminit.h>
10#include <string.h>
11#include <types.h>
12
13#include "raminit_native.h"
14
15static const uint8_t *get_spd_data_from_cbfs(struct spd_info *spdi)
16{
17 if (!CONFIG(HAVE_SPD_IN_CBFS))
18 return NULL;
19
20 printk(RAM_DEBUG, "SPD index %u\n", spdi->spd_index);
21
22 size_t spd_file_len;
23 uint8_t *spd_file = cbfs_map("spd.bin", &spd_file_len);
24
25 if (!spd_file) {
26 printk(BIOS_ERR, "SPD data not found in CBFS\n");
27 return NULL;
28 }
29
30 if (spd_file_len < ((spdi->spd_index + 1) * SPD_LEN)) {
31 printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n");
32 spdi->spd_index = 0;
33 }
34
35 if (spd_file_len < SPD_LEN) {
36 printk(BIOS_ERR, "Invalid SPD data in CBFS\n");
37 return NULL;
38 }
39
40 return spd_file + (spdi->spd_index * SPD_LEN);
41}
42
43static void get_spd_for_dimm(struct raminit_dimm_info *const dimm, const uint8_t *cbfs_spd)
44{
45 if (dimm->spd_addr == SPD_MEMORY_DOWN) {
46 if (cbfs_spd) {
47 memcpy(dimm->raw_spd, cbfs_spd, SPD_LEN);
48 dimm->valid = true;
49 printk(RAM_DEBUG, "memory-down\n");
50 return;
51 } else {
52 printk(RAM_DEBUG, "memory-down but no CBFS SPD data, ignoring\n");
53 return;
54 }
55 }
56 printk(RAM_DEBUG, "slotted ");
57 const uint8_t spd_mem_type = smbus_read_byte(dimm->spd_addr, SPD_MEMORY_TYPE);
58 if (spd_mem_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
59 printk(RAM_DEBUG, "and not DDR3, ignoring\n");
60 return;
61 }
62 printk(RAM_DEBUG, "and DDR3\n");
63 if (i2c_eeprom_read(dimm->spd_addr, 0, SPD_LEN, dimm->raw_spd) != SPD_LEN) {
64 printk(BIOS_WARNING, "I2C block read failed, trying SMBus byte reads\n");
65 for (uint32_t i = 0; i < SPD_LEN; i++)
66 dimm->raw_spd[i] = smbus_read_byte(dimm->spd_addr, i);
67 }
68 dimm->valid = true;
69}
70
71static void get_spd_data(struct sysinfo *ctrl)
72{
73 struct spd_info spdi = {0};
74 mb_get_spd_map(&spdi);
75 const uint8_t *cbfs_spd = get_spd_data_from_cbfs(&spdi);
76 for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
77 for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) {
78 struct raminit_dimm_info *const dimm = &ctrl->dimms[channel][slot];
79 dimm->spd_addr = spdi.addresses[NUM_SLOTS * channel + slot];
80 if (!dimm->spd_addr)
81 continue;
82
83 printk(RAM_DEBUG, "CH%uS%u is ", channel, slot);
84 get_spd_for_dimm(dimm, cbfs_spd);
85 }
86 }
87}
88
89static void decode_spd(struct raminit_dimm_info *const dimm)
90{
91 /** TODO: Hook up somewhere, and handle lack of XMP data **/
92 const bool enable_xmp = false;
93 memset(&dimm->data, 0, sizeof(dimm->data));
94 if (enable_xmp)
95 spd_xmp_decode_ddr3(&dimm->data, dimm->raw_spd, DDR3_XMP_PROFILE_1);
96 else
97 spd_decode_ddr3(&dimm->data, dimm->raw_spd);
98
99 if (CONFIG(DEBUG_RAM_SETUP))
100 dram_print_spd_ddr3(&dimm->data);
101}
102
103static enum raminit_status find_common_spd_parameters(struct sysinfo *ctrl)
104{
105 ctrl->cas_supported = 0xffff;
106 ctrl->flags.raw = 0xffffffff;
107
108 ctrl->tCK = 0;
109 ctrl->tAA = 0;
110 ctrl->tWR = 0;
111 ctrl->tRCD = 0;
112 ctrl->tRRD = 0;
113 ctrl->tRP = 0;
114 ctrl->tRAS = 0;
115 ctrl->tRC = 0;
116 ctrl->tRFC = 0;
117 ctrl->tWTR = 0;
118 ctrl->tRTP = 0;
119 ctrl->tFAW = 0;
120 ctrl->tCWL = 0;
121 ctrl->tCMD = 0;
122 ctrl->chanmap = 0;
123
124 bool yes_ecc = false;
125 bool not_ecc = false;
126
127 for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
128 ctrl->dpc[channel] = 0;
129 ctrl->rankmap[channel] = 0;
130 ctrl->rank_mirrored[channel] = 0;
131 ctrl->channel_size_mb[channel] = 0;
132 for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) {
133 struct raminit_dimm_info *const dimm = &ctrl->dimms[channel][slot];
134 if (!dimm->valid)
135 continue;
136
137 printk(RAM_DEBUG, "\nCH%uS%u SPD:\n", channel, slot);
138 decode_spd(dimm);
139
140 ctrl->chanmap |= BIT(channel);
141 ctrl->dpc[channel]++;
142 ctrl->channel_size_mb[channel] += dimm->data.size_mb;
143
144 /* The first rank of a populated slot is always present */
145 const uint8_t rank = slot + slot;
146 assert(dimm->data.ranks);
147 ctrl->rankmap[channel] |= (BIT(dimm->data.ranks) - 1) << rank;
148
149 if (dimm->data.flags.pins_mirrored)
150 ctrl->rank_mirrored[channel] |= BIT(rank + 1);
151
152 /* Find common settings */
153 ctrl->cas_supported &= dimm->data.cas_supported;
154 ctrl->flags.raw &= dimm->data.flags.raw;
155 ctrl->tCK = MAX(ctrl->tCK, dimm->data.tCK);
156 ctrl->tAA = MAX(ctrl->tAA, dimm->data.tAA);
157 ctrl->tWR = MAX(ctrl->tWR, dimm->data.tWR);
158 ctrl->tRCD = MAX(ctrl->tRCD, dimm->data.tRCD);
159 ctrl->tRRD = MAX(ctrl->tRRD, dimm->data.tRRD);
160 ctrl->tRP = MAX(ctrl->tRP, dimm->data.tRP);
161 ctrl->tRAS = MAX(ctrl->tRAS, dimm->data.tRAS);
162 ctrl->tRC = MAX(ctrl->tRC, dimm->data.tRC);
163 ctrl->tRFC = MAX(ctrl->tRFC, dimm->data.tRFC);
164 ctrl->tWTR = MAX(ctrl->tWTR, dimm->data.tWTR);
165 ctrl->tRTP = MAX(ctrl->tRTP, dimm->data.tRTP);
166 ctrl->tFAW = MAX(ctrl->tFAW, dimm->data.tFAW);
167 ctrl->tCWL = MAX(ctrl->tCWL, dimm->data.tCWL);
168 ctrl->tCMD = MAX(ctrl->tCMD, dimm->data.tCMD);
169
170 yes_ecc |= dimm->data.flags.is_ecc;
171 not_ecc |= !dimm->data.flags.is_ecc;
172 }
173 }
174
175 if (!ctrl->chanmap) {
176 printk(BIOS_ERR, "No DIMMs were found\n");
177 return RAMINIT_STATUS_NO_MEMORY_INSTALLED;
178 }
179 if (!ctrl->cas_supported) {
180 printk(BIOS_ERR, "Could not resolve common CAS latency\n");
181 return RAMINIT_STATUS_UNSUPPORTED_MEMORY;
182 }
183 /** TODO: Properly handle ECC support and ECC forced **/
184 if (yes_ecc && not_ecc) {
185 /** TODO: Test if the ECC DIMMs can be operated as non-ECC DIMMs **/
186 printk(BIOS_ERR, "Both ECC and non-ECC DIMMs present, this is unsupported\n");
187 return RAMINIT_STATUS_UNSUPPORTED_MEMORY;
188 }
189 if (yes_ecc)
190 ctrl->lanes = NUM_LANES;
191 else
192 ctrl->lanes = NUM_LANES_NO_ECC;
193
194 ctrl->is_ecc = yes_ecc;
195
196 /** TODO: Complete LPDDR support **/
197 ctrl->lpddr = false;
198
199 return RAMINIT_STATUS_SUCCESS;
200}
201
202enum raminit_status collect_spd_info(struct sysinfo *ctrl)
203{
204 get_spd_data(ctrl);
205 return find_common_spd_parameters(ctrl);
206}