blob: dc999138f78b18ecff3e689871c564a7d65c428b [file] [log] [blame]
Stefan Reinauer00636b02012-04-04 00:08:51 +02001/*
2 * This file is part of the coreboot project.
3 *
Stefan Reinauer00636b02012-04-04 00:08:51 +02004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
Stefan Reinauer00636b02012-04-04 00:08:51 +020013 */
14
15#include <console/console.h>
Arthur Heymans7539b8c2017-12-24 10:42:57 +010016#include <commonlib/region.h>
Kyösti Mälkki5687fc92013-11-28 18:11:49 +020017#include <bootmode.h>
Elyes HAOUASc0567292019-04-28 17:57:47 +020018#include <cf9_reset.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020019#include <string.h>
Subrata Banik53b08c32018-12-10 14:11:35 +053020#include <arch/cpu.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020021#include <device/mmio.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020022#include <device/pci_ops.h>
Kyösti Mälkki1cae4542020-01-06 12:31:34 +020023#include <device/smbus_host.h>
Stefan Reinauer00636b02012-04-04 00:08:51 +020024#include <cbmem.h>
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +010025#include <timestamp.h>
Arthur Heymans7539b8c2017-12-24 10:42:57 +010026#include <mrc_cache.h>
Patrick Rudolphfd5fa2a2016-11-11 18:22:33 +010027#include <southbridge/intel/bd82x6x/me.h>
Patrick Rudolphda9302a2019-03-24 17:01:41 +010028#include <southbridge/intel/bd82x6x/pch.h>
Patrick Rudolphfd5fa2a2016-11-11 18:22:33 +010029#include <cpu/x86/msr.h>
Elyes HAOUAS51401c32019-05-15 21:09:30 +020030#include <types.h>
Elyes HAOUASbf0970e2019-03-21 11:10:03 +010031
Patrick Rudolphfd5fa2a2016-11-11 18:22:33 +010032#include "raminit_native.h"
33#include "raminit_common.h"
34#include "sandybridge.h"
Stefan Reinauer00636b02012-04-04 00:08:51 +020035
Angel Pons7c49cb82020-03-16 23:17:32 +010036/* FIXME: no ECC support */
37/* FIXME: no support for 3-channel chipsets */
Stefan Reinauer00636b02012-04-04 00:08:51 +020038
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070039static void wait_txt_clear(void)
40{
Angel Pons7c49cb82020-03-16 23:17:32 +010041 struct cpuid_result cp = cpuid_ext(1, 0);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070042
Angel Pons7c49cb82020-03-16 23:17:32 +010043 /* Check if TXT is supported */
44 if (!(cp.ecx & (1 << 6)))
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070045 return;
Angel Pons7c49cb82020-03-16 23:17:32 +010046
47 /* Some TXT public bit */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070048 if (!(read32((void *)0xfed30010) & 1))
49 return;
Angel Pons7c49cb82020-03-16 23:17:32 +010050
51 /* Wait for TXT clear */
52 while (!(read8((void *)0xfed40000) & (1 << 7)))
53 ;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070054}
55
Angel Pons7c49cb82020-03-16 23:17:32 +010056/* Disable a channel in ramctr_timing */
57static void disable_channel(ramctr_timing *ctrl, int channel)
58{
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +010059 ctrl->rankmap[channel] = 0;
Angel Pons7c49cb82020-03-16 23:17:32 +010060
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +010061 memset(&ctrl->rank_mirror[channel][0], 0, sizeof(ctrl->rank_mirror[0]));
Angel Pons7c49cb82020-03-16 23:17:32 +010062
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +010063 ctrl->channel_size_mb[channel] = 0;
Angel Pons7c49cb82020-03-16 23:17:32 +010064 ctrl->cmd_stretch[channel] = 0;
65 ctrl->mad_dimm[channel] = 0;
66 memset(&ctrl->timings[channel][0], 0, sizeof(ctrl->timings[0]));
Patrick Rudolph74163d62016-11-17 20:02:43 +010067 memset(&ctrl->info.dimm[channel][0], 0, sizeof(ctrl->info.dimm[0]));
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +010068}
69
Angel Pons7c49cb82020-03-16 23:17:32 +010070/* Fill cbmem with information for SMBIOS type 17 */
Patrick Rudolph735ecce2016-03-26 10:42:27 +010071static void fill_smbios17(ramctr_timing *ctrl)
Patrick Rudolphb97009e2016-02-28 15:24:04 +010072{
Patrick Rudolphb97009e2016-02-28 15:24:04 +010073 int channel, slot;
Patrick Rudolph24efe732018-08-19 11:06:06 +020074 const u16 ddr_freq = (1000 << 8) / ctrl->tCK;
Patrick Rudolphb97009e2016-02-28 15:24:04 +010075
Elyes HAOUAS12df9502016-08-23 21:29:48 +020076 FOR_ALL_CHANNELS for (slot = 0; slot < NUM_SLOTS; slot++) {
Patrick Rudolph24efe732018-08-19 11:06:06 +020077 enum cb_err ret = spd_add_smbios17(channel, slot, ddr_freq,
78 &ctrl->info.dimm[channel][slot]);
79 if (ret != CB_SUCCESS)
80 printk(BIOS_ERR, "RAMINIT: Failed to add SMBIOS17\n");
Patrick Rudolphb97009e2016-02-28 15:24:04 +010081 }
82}
83
Angel Pons7c49cb82020-03-16 23:17:32 +010084/* Return CRC16 match for all SPDs */
Patrick Rudolph56abd4d2016-03-13 11:07:45 +010085static int verify_crc16_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
86{
87 int channel, slot, spd_slot;
88 int match = 1;
89
90 FOR_ALL_CHANNELS {
91 for (slot = 0; slot < NUM_SLOTS; slot++) {
92 spd_slot = 2 * channel + slot;
93 match &= ctrl->spd_crc[channel][slot] ==
Angel Pons7c49cb82020-03-16 23:17:32 +010094 spd_ddr3_calc_unique_crc(spd[spd_slot], sizeof(spd_raw_data));
Patrick Rudolph56abd4d2016-03-13 11:07:45 +010095 }
96 }
97 return match;
98}
99
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +0200100void read_spd(spd_raw_data * spd, u8 addr, bool id_only)
Stefan Reinauer00636b02012-04-04 00:08:51 +0200101{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700102 int j;
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +0200103 if (id_only) {
104 for (j = 117; j < 128; j++)
105 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
106 } else {
107 for (j = 0; j < 256; j++)
108 (*spd)[j] = do_smbus_read_byte(SMBUS_IO_BASE, addr, j);
109 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700110}
111
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100112static void dram_find_spds_ddr3(spd_raw_data *spd, ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700113{
Angel Pons7c49cb82020-03-16 23:17:32 +0100114 int dimms = 0, ch_dimms;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700115 int channel, slot, spd_slot;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100116 dimm_info *dimm = &ctrl->info;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700117
Elyes HAOUAS0d4b11a2016-10-03 21:57:21 +0200118 memset (ctrl->rankmap, 0, sizeof(ctrl->rankmap));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700119
120 ctrl->extended_temperature_range = 1;
121 ctrl->auto_self_refresh = 1;
122
123 FOR_ALL_CHANNELS {
124 ctrl->channel_size_mb[channel] = 0;
125
Angel Pons7c49cb82020-03-16 23:17:32 +0100126 ch_dimms = 0;
127 /* Count dimms on channel */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700128 for (slot = 0; slot < NUM_SLOTS; slot++) {
129 spd_slot = 2 * channel + slot;
Angel Pons7c49cb82020-03-16 23:17:32 +0100130 printk(BIOS_DEBUG, "SPD probe channel%d, slot%d\n", channel, slot);
Patrick Rudolph5a061852017-09-22 15:19:26 +0200131
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700132 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100133 if (dimm->dimm[channel][slot].dram_type == SPD_MEMORY_TYPE_SDRAM_DDR3)
Angel Pons7c49cb82020-03-16 23:17:32 +0100134 ch_dimms++;
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100135 }
136
137 for (slot = 0; slot < NUM_SLOTS; slot++) {
138 spd_slot = 2 * channel + slot;
Angel Pons7c49cb82020-03-16 23:17:32 +0100139 printk(BIOS_DEBUG, "SPD probe channel%d, slot%d\n", channel, slot);
Patrick Rudolph5a061852017-09-22 15:19:26 +0200140
Angel Pons7c49cb82020-03-16 23:17:32 +0100141 /* Search for XMP profile */
142 spd_xmp_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot],
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100143 DDR3_XMP_PROFILE_1);
144
145 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
146 printram("No valid XMP profile found.\n");
147 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
Angel Pons7c49cb82020-03-16 23:17:32 +0100148
149 } else if (ch_dimms > dimm->dimm[channel][slot].dimms_per_channel) {
150 printram(
151 "XMP profile supports %u DIMMs, but %u DIMMs are installed.\n",
152 dimm->dimm[channel][slot].dimms_per_channel, ch_dimms);
153
Julius Wernercd49cce2019-03-05 16:53:33 -0800154 if (CONFIG(NATIVE_RAMINIT_IGNORE_XMP_MAX_DIMMS))
Angel Pons7c49cb82020-03-16 23:17:32 +0100155 printk(BIOS_WARNING,
156 "XMP maximum DIMMs will be ignored.\n");
Vagiz Trakhanov771be482017-10-02 10:02:35 +0000157 else
Angel Pons7c49cb82020-03-16 23:17:32 +0100158 spd_decode_ddr3(&dimm->dimm[channel][slot],
159 spd[spd_slot]);
160
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100161 } else if (dimm->dimm[channel][slot].voltage != 1500) {
Angel Pons7c49cb82020-03-16 23:17:32 +0100162 /* TODO: Support DDR3 voltages other than 1500mV */
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100163 printram("XMP profile's requested %u mV is unsupported.\n",
164 dimm->dimm[channel][slot].voltage);
165 spd_decode_ddr3(&dimm->dimm[channel][slot], spd[spd_slot]);
166 }
167
Angel Pons7c49cb82020-03-16 23:17:32 +0100168 /* Fill in CRC16 for MRC cache */
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100169 ctrl->spd_crc[channel][slot] =
Angel Pons7c49cb82020-03-16 23:17:32 +0100170 spd_ddr3_calc_unique_crc(spd[spd_slot], sizeof(spd_raw_data));
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100171
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700172 if (dimm->dimm[channel][slot].dram_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
Angel Pons7c49cb82020-03-16 23:17:32 +0100173 /* Mark DIMM as invalid */
174 dimm->dimm[channel][slot].ranks = 0;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700175 dimm->dimm[channel][slot].size_mb = 0;
176 continue;
177 }
178
179 dram_print_spd_ddr3(&dimm->dimm[channel][slot]);
180 dimms++;
181 ctrl->rank_mirror[channel][slot * 2] = 0;
Angel Pons7c49cb82020-03-16 23:17:32 +0100182 ctrl->rank_mirror[channel][slot * 2 + 1] =
183 dimm->dimm[channel][slot].flags.pins_mirrored;
184
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700185 ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb;
186
187 ctrl->auto_self_refresh &= dimm->dimm[channel][slot].flags.asr;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700188
Angel Pons7c49cb82020-03-16 23:17:32 +0100189 ctrl->extended_temperature_range &=
190 dimm->dimm[channel][slot].flags.ext_temp_refresh;
191
192 ctrl->rankmap[channel] |=
193 ((1 << dimm->dimm[channel][slot].ranks) - 1) << (2 * slot);
194
195 printk(BIOS_DEBUG, "channel[%d] rankmap = 0x%x\n", channel,
196 ctrl->rankmap[channel]);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700197 }
Angel Pons7c49cb82020-03-16 23:17:32 +0100198 if ((ctrl->rankmap[channel] & 0x03) && (ctrl->rankmap[channel] & 0x0c)
199 && dimm->dimm[channel][0].reference_card <= 5
200 && dimm->dimm[channel][1].reference_card <= 5) {
201
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700202 const int ref_card_offset_table[6][6] = {
Angel Pons7c49cb82020-03-16 23:17:32 +0100203 { 0, 0, 0, 0, 2, 2 },
204 { 0, 0, 0, 0, 2, 2 },
205 { 0, 0, 0, 0, 2, 2 },
206 { 0, 0, 0, 0, 1, 1 },
207 { 2, 2, 2, 1, 0, 0 },
208 { 2, 2, 2, 1, 0, 0 },
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700209 };
Angel Pons7c49cb82020-03-16 23:17:32 +0100210 ctrl->ref_card_offset[channel] = ref_card_offset_table
211 [dimm->dimm[channel][0].reference_card]
212 [dimm->dimm[channel][1].reference_card];
213 } else {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700214 ctrl->ref_card_offset[channel] = 0;
Angel Pons7c49cb82020-03-16 23:17:32 +0100215 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700216 }
217
218 if (!dimms)
219 die("No DIMMs were found");
220}
221
Patrick Rudolphbb9c90a2016-05-29 17:05:06 +0200222static void save_timings(ramctr_timing *ctrl)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700223{
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700224 /* Save the MRC S3 restore data to cbmem */
Angel Pons7c49cb82020-03-16 23:17:32 +0100225 mrc_cache_stash_data(MRC_TRAINING_DATA, MRC_CACHE_VERSION, ctrl, sizeof(*ctrl));
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700226}
227
Angel Pons7c49cb82020-03-16 23:17:32 +0100228static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot, int s3resume, int me_uma_size)
Patrick Rudolph27e085a2016-03-26 10:59:02 +0100229{
Patrick Rudolph305035c2016-11-11 18:38:50 +0100230 if (ctrl->sandybridge)
Angel Pons7c49cb82020-03-16 23:17:32 +0100231 return try_init_dram_ddr3_snb(ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100232 else
Angel Pons7c49cb82020-03-16 23:17:32 +0100233 return try_init_dram_ddr3_ivb(ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph27e085a2016-03-26 10:59:02 +0100234}
235
Patrick Rudolph74203de2017-11-20 11:57:01 +0100236static void init_dram_ddr3(int min_tck, int s3resume)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700237{
Angel Pons7c49cb82020-03-16 23:17:32 +0100238 int me_uma_size, cbmem_was_inited, fast_boot, err;
Patrick Rudolph735ecce2016-03-26 10:42:27 +0100239 ramctr_timing ctrl;
Kyösti Mälkki4cb44e52016-11-18 19:11:24 +0200240 spd_raw_data spds[4];
Arthur Heymans7539b8c2017-12-24 10:42:57 +0100241 struct region_device rdev;
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100242 ramctr_timing *ctrl_cached;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100243 u32 cpu;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700244
Angel Pons88521882020-01-05 20:21:20 +0100245 MCHBAR32(SAPMCTL) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200246
247 /* Wait for ME to be ready */
248 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700249 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +0200250
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700251 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +0200252
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700253 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +0200254
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700255 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +0200256
Angel Pons7c49cb82020-03-16 23:17:32 +0100257 const u32 sskpd = MCHBAR32(SSKPD); // !!! = 0x00000000
258 if ((pci_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 && sskpd && !s3resume) {
259 MCHBAR32(SSKPD) = 0;
260 /* Need reset */
Elyes HAOUASc0567292019-04-28 17:57:47 +0200261 system_reset();
Stefan Reinauer00636b02012-04-04 00:08:51 +0200262 }
Stefan Reinauer00636b02012-04-04 00:08:51 +0200263
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700264 early_pch_init_native();
Patrick Rudolph6aca7e62019-03-26 18:22:36 +0100265 early_init_dmi();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700266 early_thermal_init();
267
Angel Pons7c49cb82020-03-16 23:17:32 +0100268 /* Try to find timings in MRC cache */
269 err = mrc_cache_get_current(MRC_TRAINING_DATA, MRC_CACHE_VERSION, &rdev);
270 if (err || (region_device_sz(&rdev) < sizeof(ctrl))) {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100271 if (s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700272 /* Failed S3 resume, reset to come up cleanly */
Elyes HAOUASc0567292019-04-28 17:57:47 +0200273 system_reset();
Stefan Reinauer00636b02012-04-04 00:08:51 +0200274 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100275 ctrl_cached = NULL;
Patrick Rudolph27e085a2016-03-26 10:59:02 +0100276 } else {
Arthur Heymans7539b8c2017-12-24 10:42:57 +0100277 ctrl_cached = rdev_mmap_full(&rdev);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700278 }
279
Angel Pons7c49cb82020-03-16 23:17:32 +0100280 /* Verify MRC cache for fast boot */
Kyösti Mälkki38cb8222016-11-18 19:25:52 +0200281 if (!s3resume && ctrl_cached) {
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +0200282 /* Load SPD unique information data. */
283 memset(spds, 0, sizeof(spds));
284 mainboard_get_spd(spds, 1);
285
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100286 /* check SPD CRC16 to make sure the DIMMs haven't been replaced */
287 fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
288 if (!fast_boot)
289 printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
Kyösti Mälkki38cb8222016-11-18 19:25:52 +0200290 } else {
291 fast_boot = s3resume;
292 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100293
294 if (fast_boot) {
295 printk(BIOS_DEBUG, "Trying stored timings.\n");
296 memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
297
Patrick Rudolph588ccaa2016-04-20 18:00:27 +0200298 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100299 if (err) {
Patrick Rudolph588ccaa2016-04-20 18:00:27 +0200300 if (s3resume) {
301 /* Failed S3 resume, reset to come up cleanly */
Elyes HAOUASc0567292019-04-28 17:57:47 +0200302 system_reset();
Patrick Rudolph588ccaa2016-04-20 18:00:27 +0200303 }
Angel Pons7c49cb82020-03-16 23:17:32 +0100304 /* No need to erase bad MRC cache here, it gets overwritten on a
305 successful boot */
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100306 printk(BIOS_ERR, "Stored timings are invalid !\n");
307 fast_boot = 0;
308 }
309 }
310 if (!fast_boot) {
Patrick Rudolphe74ad212016-11-16 18:06:50 +0100311 /* Reset internal state */
312 memset(&ctrl, 0, sizeof(ctrl));
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100313 ctrl.tCK = min_tck;
314
Patrick Rudolph305035c2016-11-11 18:38:50 +0100315 /* Get architecture */
Subrata Banik53b08c32018-12-10 14:11:35 +0530316 cpu = cpu_get_cpuid();
Patrick Rudolph305035c2016-11-11 18:38:50 +0100317 ctrl.sandybridge = IS_SANDY_CPU(cpu);
318
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100319 /* Get DDR3 SPD data */
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +0200320 memset(spds, 0, sizeof(spds));
321 mainboard_get_spd(spds, 0);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100322 dram_find_spds_ddr3(spds, &ctrl);
323
Patrick Rudolph588ccaa2016-04-20 18:00:27 +0200324 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100325 }
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100326
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100327 if (err) {
Angel Pons7c49cb82020-03-16 23:17:32 +0100328 /* Fallback: disable failing channel */
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100329 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
330 printram("Disable failing channel.\n");
331
Patrick Rudolphe74ad212016-11-16 18:06:50 +0100332 /* Reset internal state */
333 memset(&ctrl, 0, sizeof(ctrl));
Patrick Rudolphe74ad212016-11-16 18:06:50 +0100334 ctrl.tCK = min_tck;
335
Patrick Rudolph305035c2016-11-11 18:38:50 +0100336 /* Get architecture */
Subrata Banik53b08c32018-12-10 14:11:35 +0530337 cpu = cpu_get_cpuid();
Patrick Rudolph305035c2016-11-11 18:38:50 +0100338 ctrl.sandybridge = IS_SANDY_CPU(cpu);
339
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100340 /* Reset DDR3 frequency */
341 dram_find_spds_ddr3(spds, &ctrl);
342
Angel Pons7c49cb82020-03-16 23:17:32 +0100343 /* Disable failing channel */
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100344 disable_channel(&ctrl, GET_ERR_CHANNEL(err));
345
346 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
347 }
348
Patrick Rudolph31d19592016-03-26 12:22:34 +0100349 if (err)
350 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700351
Angel Pons88521882020-01-05 20:21:20 +0100352 /* FIXME: should be hardware revision-dependent. The register only exists on IVB. */
353 MCHBAR32(CHANNEL_HASH) = 0x00a030ce;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700354
355 set_scrambling_seed(&ctrl);
356
Angel Pons88521882020-01-05 20:21:20 +0100357 set_normal_operation(&ctrl);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700358
359 final_registers(&ctrl);
360
361 /* Zone config */
362 dram_zones(&ctrl, 0);
363
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700364 intel_early_me_status();
365 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
366 intel_early_me_status();
367
Stefan Reinauer00636b02012-04-04 00:08:51 +0200368 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700369
370 cbmem_was_inited = !cbmem_recovery(s3resume);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100371 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700372 save_timings(&ctrl);
373 if (s3resume && !cbmem_was_inited) {
374 /* Failed S3 resume, reset to come up cleanly */
Elyes HAOUASc0567292019-04-28 17:57:47 +0200375 system_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700376 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100377
Nico Huber9ce59742018-09-13 10:52:44 +0200378 if (!s3resume)
379 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200380}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100381
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100382void perform_raminit(int s3resume)
383{
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100384 post_code(0x3a);
385
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100386 timestamp_add_now(TS_BEFORE_INITRAM);
387
Patrick Rudolph74203de2017-11-20 11:57:01 +0100388 init_dram_ddr3(get_mem_min_tck(), s3resume);
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100389}