blob: 2a3e4d73e3c06f9714311e180d4a408f45ffa529 [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{
Angel Pons80037f72020-03-21 13:12:37 +0100230 if (IS_SANDY_CPU(ctrl->cpu))
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
Angel Pons80037f72020-03-21 13:12:37 +0100236static void init_dram_ddr3(int min_tck, int s3resume, const u32 cpuid)
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;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700243
Angel Pons88521882020-01-05 20:21:20 +0100244 MCHBAR32(SAPMCTL) |= 1;
Stefan Reinauer00636b02012-04-04 00:08:51 +0200245
246 /* Wait for ME to be ready */
247 intel_early_me_init();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700248 me_uma_size = intel_early_me_uma_size();
Stefan Reinauer00636b02012-04-04 00:08:51 +0200249
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700250 printk(BIOS_DEBUG, "Starting native Platform init\n");
Stefan Reinauer00636b02012-04-04 00:08:51 +0200251
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700252 wait_txt_clear();
Stefan Reinauer00636b02012-04-04 00:08:51 +0200253
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700254 wrmsr(0x000002e6, (msr_t) { .lo = 0, .hi = 0 });
Stefan Reinauer00636b02012-04-04 00:08:51 +0200255
Angel Pons7c49cb82020-03-16 23:17:32 +0100256 const u32 sskpd = MCHBAR32(SSKPD); // !!! = 0x00000000
257 if ((pci_read_config16(SOUTHBRIDGE, 0xa2) & 0xa0) == 0x20 && sskpd && !s3resume) {
258 MCHBAR32(SSKPD) = 0;
259 /* Need reset */
Elyes HAOUASc0567292019-04-28 17:57:47 +0200260 system_reset();
Stefan Reinauer00636b02012-04-04 00:08:51 +0200261 }
Stefan Reinauer00636b02012-04-04 00:08:51 +0200262
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700263 early_pch_init_native();
Patrick Rudolph6aca7e62019-03-26 18:22:36 +0100264 early_init_dmi();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700265 early_thermal_init();
266
Angel Pons7c49cb82020-03-16 23:17:32 +0100267 /* Try to find timings in MRC cache */
268 err = mrc_cache_get_current(MRC_TRAINING_DATA, MRC_CACHE_VERSION, &rdev);
269 if (err || (region_device_sz(&rdev) < sizeof(ctrl))) {
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100270 if (s3resume) {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700271 /* Failed S3 resume, reset to come up cleanly */
Elyes HAOUASc0567292019-04-28 17:57:47 +0200272 system_reset();
Stefan Reinauer00636b02012-04-04 00:08:51 +0200273 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100274 ctrl_cached = NULL;
Patrick Rudolph27e085a2016-03-26 10:59:02 +0100275 } else {
Arthur Heymans7539b8c2017-12-24 10:42:57 +0100276 ctrl_cached = rdev_mmap_full(&rdev);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700277 }
278
Angel Pons7c49cb82020-03-16 23:17:32 +0100279 /* Verify MRC cache for fast boot */
Kyösti Mälkki38cb8222016-11-18 19:25:52 +0200280 if (!s3resume && ctrl_cached) {
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +0200281 /* Load SPD unique information data. */
282 memset(spds, 0, sizeof(spds));
283 mainboard_get_spd(spds, 1);
284
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100285 /* check SPD CRC16 to make sure the DIMMs haven't been replaced */
286 fast_boot = verify_crc16_spds_ddr3(spds, ctrl_cached);
287 if (!fast_boot)
288 printk(BIOS_DEBUG, "Stored timings CRC16 mismatch.\n");
Kyösti Mälkki38cb8222016-11-18 19:25:52 +0200289 } else {
290 fast_boot = s3resume;
291 }
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100292
293 if (fast_boot) {
294 printk(BIOS_DEBUG, "Trying stored timings.\n");
295 memcpy(&ctrl, ctrl_cached, sizeof(ctrl));
296
Patrick Rudolph588ccaa2016-04-20 18:00:27 +0200297 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100298 if (err) {
Patrick Rudolph588ccaa2016-04-20 18:00:27 +0200299 if (s3resume) {
300 /* Failed S3 resume, reset to come up cleanly */
Elyes HAOUASc0567292019-04-28 17:57:47 +0200301 system_reset();
Patrick Rudolph588ccaa2016-04-20 18:00:27 +0200302 }
Angel Pons7c49cb82020-03-16 23:17:32 +0100303 /* No need to erase bad MRC cache here, it gets overwritten on a
304 successful boot */
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100305 printk(BIOS_ERR, "Stored timings are invalid !\n");
306 fast_boot = 0;
307 }
308 }
309 if (!fast_boot) {
Patrick Rudolphe74ad212016-11-16 18:06:50 +0100310 /* Reset internal state */
311 memset(&ctrl, 0, sizeof(ctrl));
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100312 ctrl.tCK = min_tck;
313
Patrick Rudolph305035c2016-11-11 18:38:50 +0100314 /* Get architecture */
Angel Pons80037f72020-03-21 13:12:37 +0100315 ctrl.cpu = cpuid;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100316
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100317 /* Get DDR3 SPD data */
Kyösti Mälkkie258b9a2016-11-18 19:59:23 +0200318 memset(spds, 0, sizeof(spds));
319 mainboard_get_spd(spds, 0);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100320 dram_find_spds_ddr3(spds, &ctrl);
321
Patrick Rudolph588ccaa2016-04-20 18:00:27 +0200322 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100323 }
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100324
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100325 if (err) {
Angel Pons7c49cb82020-03-16 23:17:32 +0100326 /* Fallback: disable failing channel */
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100327 printk(BIOS_ERR, "RAM training failed, trying fallback.\n");
328 printram("Disable failing channel.\n");
329
Patrick Rudolphe74ad212016-11-16 18:06:50 +0100330 /* Reset internal state */
331 memset(&ctrl, 0, sizeof(ctrl));
Patrick Rudolphe74ad212016-11-16 18:06:50 +0100332 ctrl.tCK = min_tck;
333
Patrick Rudolph305035c2016-11-11 18:38:50 +0100334 /* Get architecture */
Angel Pons80037f72020-03-21 13:12:37 +0100335 ctrl.cpu = cpuid;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100336
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100337 /* Reset DDR3 frequency */
338 dram_find_spds_ddr3(spds, &ctrl);
339
Angel Pons7c49cb82020-03-16 23:17:32 +0100340 /* Disable failing channel */
Patrick Rudolph2ccb74b2016-03-26 12:16:29 +0100341 disable_channel(&ctrl, GET_ERR_CHANNEL(err));
342
343 err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size);
344 }
345
Patrick Rudolph31d19592016-03-26 12:22:34 +0100346 if (err)
347 die("raminit failed");
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700348
Angel Pons88521882020-01-05 20:21:20 +0100349 /* FIXME: should be hardware revision-dependent. The register only exists on IVB. */
350 MCHBAR32(CHANNEL_HASH) = 0x00a030ce;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700351
352 set_scrambling_seed(&ctrl);
353
Angel Pons88521882020-01-05 20:21:20 +0100354 set_normal_operation(&ctrl);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700355
356 final_registers(&ctrl);
357
358 /* Zone config */
359 dram_zones(&ctrl, 0);
360
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700361 intel_early_me_status();
362 intel_early_me_init_done(ME_INIT_STATUS_SUCCESS);
363 intel_early_me_status();
364
Stefan Reinauer00636b02012-04-04 00:08:51 +0200365 report_memory_config();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700366
367 cbmem_was_inited = !cbmem_recovery(s3resume);
Patrick Rudolph56abd4d2016-03-13 11:07:45 +0100368 if (!fast_boot)
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700369 save_timings(&ctrl);
370 if (s3resume && !cbmem_was_inited) {
371 /* Failed S3 resume, reset to come up cleanly */
Elyes HAOUASc0567292019-04-28 17:57:47 +0200372 system_reset();
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700373 }
Patrick Rudolphb97009e2016-02-28 15:24:04 +0100374
Nico Huber9ce59742018-09-13 10:52:44 +0200375 if (!s3resume)
376 fill_smbios17(&ctrl);
Stefan Reinauer00636b02012-04-04 00:08:51 +0200377}
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100378
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100379void perform_raminit(int s3resume)
380{
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100381 post_code(0x3a);
382
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100383 timestamp_add_now(TS_BEFORE_INITRAM);
384
Angel Pons80037f72020-03-21 13:12:37 +0100385 init_dram_ddr3(get_mem_min_tck(), s3resume, cpu_get_cpuid());
Vladimir Serbinenkoffbb3c02016-02-10 01:36:25 +0100386}