blob: a823d503984ebbb482320aead0230c96aec2d0fd [file] [log] [blame]
Patrick Rudolph305035c2016-11-11 18:38:50 +01001/*
2 * This file is part of the coreboot project.
3 *
Patrick Rudolph305035c2016-11-11 18:38:50 +01004 *
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.
13 */
14
15#include <console/console.h>
16#include <console/usb.h>
Patrick Rudolph305035c2016-11-11 18:38:50 +010017#include <delay.h>
18#include "raminit_native.h"
19#include "raminit_common.h"
20
Angel Pons7c49cb82020-03-16 23:17:32 +010021/* Frequency multiplier */
Patrick Rudolph305035c2016-11-11 18:38:50 +010022static u32 get_FRQ(u32 tCK)
23{
Angel Pons7c49cb82020-03-16 23:17:32 +010024 const u32 FRQ = 256000 / (tCK * BASEFREQ);
25
Patrick Rudolph305035c2016-11-11 18:38:50 +010026 if (FRQ > 8)
27 return 8;
28 if (FRQ < 3)
29 return 3;
Angel Pons7c49cb82020-03-16 23:17:32 +010030
Patrick Rudolph305035c2016-11-11 18:38:50 +010031 return FRQ;
32}
33
Angel Pons7c49cb82020-03-16 23:17:32 +010034/* Get REFI based on MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +010035static u32 get_REFI(u32 tCK)
36{
Angel Pons7c49cb82020-03-16 23:17:32 +010037 static const u32 frq_refi_map[] = {
38 /* FRQ: 3, 4, 5, 6, 7, 8, */
39 3120, 4160, 5200, 6240, 7280, 8320,
40 };
Patrick Rudolph305035c2016-11-11 18:38:50 +010041 return frq_refi_map[get_FRQ(tCK) - 3];
42}
43
Angel Pons7c49cb82020-03-16 23:17:32 +010044/* Get XSOffset based on MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +010045static u8 get_XSOffset(u32 tCK)
46{
Angel Pons7c49cb82020-03-16 23:17:32 +010047 static const u8 frq_xs_map[] = {
48 /* FRQ: 3, 4, 5, 6, 7, 8, */
49 4, 6, 7, 8, 10, 11,
50 };
Patrick Rudolph305035c2016-11-11 18:38:50 +010051 return frq_xs_map[get_FRQ(tCK) - 3];
52}
53
Angel Pons7c49cb82020-03-16 23:17:32 +010054/* Get MOD based on MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +010055static u8 get_MOD(u32 tCK)
56{
Angel Pons7c49cb82020-03-16 23:17:32 +010057 static const u8 frq_mod_map[] = {
58 /* FRQ: 3, 4, 5, 6, 7, 8, */
59 12, 12, 12, 12, 15, 16,
60 };
Patrick Rudolph305035c2016-11-11 18:38:50 +010061 return frq_mod_map[get_FRQ(tCK) - 3];
62}
63
Angel Pons7c49cb82020-03-16 23:17:32 +010064/* Get Write Leveling Output delay based on MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +010065static u8 get_WLO(u32 tCK)
66{
Angel Pons7c49cb82020-03-16 23:17:32 +010067 static const u8 frq_wlo_map[] = {
68 /* FRQ: 3, 4, 5, 6, 7, 8, */
69 4, 5, 6, 6, 8, 8,
70 };
Patrick Rudolph305035c2016-11-11 18:38:50 +010071 return frq_wlo_map[get_FRQ(tCK) - 3];
72}
73
Angel Pons7c49cb82020-03-16 23:17:32 +010074/* Get CKE based on MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +010075static u8 get_CKE(u32 tCK)
76{
Angel Pons7c49cb82020-03-16 23:17:32 +010077 static const u8 frq_cke_map[] = {
78 /* FRQ: 3, 4, 5, 6, 7, 8, */
79 3, 3, 4, 4, 5, 6,
80 };
Patrick Rudolph305035c2016-11-11 18:38:50 +010081 return frq_cke_map[get_FRQ(tCK) - 3];
82}
83
Angel Pons7c49cb82020-03-16 23:17:32 +010084/* Get XPDLL based on MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +010085static u8 get_XPDLL(u32 tCK)
86{
Angel Pons7c49cb82020-03-16 23:17:32 +010087 static const u8 frq_xpdll_map[] = {
88 /* FRQ: 3, 4, 5, 6, 7, 8, */
89 10, 13, 16, 20, 23, 26,
90 };
Patrick Rudolph305035c2016-11-11 18:38:50 +010091 return frq_xpdll_map[get_FRQ(tCK) - 3];
92}
93
Angel Pons7c49cb82020-03-16 23:17:32 +010094/* Get XP based on MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +010095static u8 get_XP(u32 tCK)
96{
Angel Pons7c49cb82020-03-16 23:17:32 +010097 static const u8 frq_xp_map[] = {
98 /* FRQ: 3, 4, 5, 6, 7, 8, */
99 3, 4, 4, 5, 6, 7,
100 };
Patrick Rudolph305035c2016-11-11 18:38:50 +0100101 return frq_xp_map[get_FRQ(tCK) - 3];
102}
103
Angel Pons7c49cb82020-03-16 23:17:32 +0100104/* Get AONPD based on MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100105static u8 get_AONPD(u32 tCK)
106{
Angel Pons7c49cb82020-03-16 23:17:32 +0100107 static const u8 frq_aonpd_map[] = {
108 /* FRQ: 3, 4, 5, 6, 7, 8, */
109 4, 5, 6, 8, 8, 10,
110 };
Patrick Rudolph305035c2016-11-11 18:38:50 +0100111 return frq_aonpd_map[get_FRQ(tCK) - 3];
112}
113
Angel Pons7c49cb82020-03-16 23:17:32 +0100114/* Get COMP2 based on MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100115static u32 get_COMP2(u32 tCK)
116{
Angel Pons7c49cb82020-03-16 23:17:32 +0100117 static const u32 frq_comp2_map[] = {
118 /* FRQ: 3, 4, 5, 6, 7, 8, */
119 0x0D6BEDCC, 0x0CE7C34C, 0x0CA57A4C, 0x0C6369CC, 0x0C42514C, 0x0C21410C,
Patrick Rudolph305035c2016-11-11 18:38:50 +0100120 };
121 return frq_comp2_map[get_FRQ(tCK) - 3];
122}
123
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200124static void snb_normalize_tclk(u32 *tclk)
125{
126 if (*tclk <= TCK_1066MHZ) {
127 *tclk = TCK_1066MHZ;
128 } else if (*tclk <= TCK_933MHZ) {
129 *tclk = TCK_933MHZ;
130 } else if (*tclk <= TCK_800MHZ) {
131 *tclk = TCK_800MHZ;
132 } else if (*tclk <= TCK_666MHZ) {
133 *tclk = TCK_666MHZ;
134 } else if (*tclk <= TCK_533MHZ) {
135 *tclk = TCK_533MHZ;
136 } else if (*tclk <= TCK_400MHZ) {
137 *tclk = TCK_400MHZ;
138 } else {
139 *tclk = 0;
140 }
141}
142
143static void find_cas_tck(ramctr_timing *ctrl)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100144{
145 u8 val;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100146
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200147 /* Find CAS latency */
148 while (1) {
Angel Pons7c49cb82020-03-16 23:17:32 +0100149 /*
150 * Normalising tCK before computing clock could potentially
151 * result in a lower selected CAS, which is desired.
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200152 */
153 snb_normalize_tclk(&(ctrl->tCK));
154 if (!(ctrl->tCK))
155 die("Couldn't find compatible clock / CAS settings\n");
Angel Pons7c49cb82020-03-16 23:17:32 +0100156
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200157 val = DIV_ROUND_UP(ctrl->tAA, ctrl->tCK);
158 printk(BIOS_DEBUG, "Trying CAS %u, tCK %u.\n", val, ctrl->tCK);
159 for (; val <= MAX_CAS; val++)
160 if ((ctrl->cas_supported >> (val - MIN_CAS)) & 1)
161 break;
Angel Pons7c49cb82020-03-16 23:17:32 +0100162
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200163 if (val == (MAX_CAS + 1)) {
164 ctrl->tCK++;
165 continue;
166 } else {
167 printk(BIOS_DEBUG, "Found compatible clock, CAS pair.\n");
168 break;
169 }
170 }
171
Angel Pons7c49cb82020-03-16 23:17:32 +0100172 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", NS2MHZ_DIV256 / ctrl->tCK);
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200173 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
174 ctrl->CAS = val;
175}
176
177static void dram_timing(ramctr_timing *ctrl)
178{
Angel Pons7c49cb82020-03-16 23:17:32 +0100179 /*
180 * On Sandy Bridge, the maximum supported DDR3 frequency is 1066MHz (DDR3 2133).
181 * Cap it for faster DIMMs, and align it to the closest JEDEC standard frequency.
182 */
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200183 if (ctrl->tCK == TCK_1066MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100184 ctrl->edge_offset[0] = 16;
185 ctrl->edge_offset[1] = 7;
186 ctrl->edge_offset[2] = 7;
187 ctrl->timC_offset[0] = 18;
188 ctrl->timC_offset[1] = 7;
189 ctrl->timC_offset[2] = 7;
Angel Pons88521882020-01-05 20:21:20 +0100190 ctrl->pi_coding_threshold = 13;
Angel Pons7c49cb82020-03-16 23:17:32 +0100191
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200192 } else if (ctrl->tCK == TCK_933MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100193 ctrl->edge_offset[0] = 14;
194 ctrl->edge_offset[1] = 6;
195 ctrl->edge_offset[2] = 6;
196 ctrl->timC_offset[0] = 15;
197 ctrl->timC_offset[1] = 6;
198 ctrl->timC_offset[2] = 6;
Angel Pons88521882020-01-05 20:21:20 +0100199 ctrl->pi_coding_threshold = 15;
Angel Pons7c49cb82020-03-16 23:17:32 +0100200
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200201 } else if (ctrl->tCK == TCK_800MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100202 ctrl->edge_offset[0] = 13;
203 ctrl->edge_offset[1] = 5;
204 ctrl->edge_offset[2] = 5;
205 ctrl->timC_offset[0] = 14;
206 ctrl->timC_offset[1] = 5;
207 ctrl->timC_offset[2] = 5;
Angel Pons88521882020-01-05 20:21:20 +0100208 ctrl->pi_coding_threshold = 15;
Angel Pons7c49cb82020-03-16 23:17:32 +0100209
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200210 } else if (ctrl->tCK == TCK_666MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100211 ctrl->edge_offset[0] = 10;
212 ctrl->edge_offset[1] = 4;
213 ctrl->edge_offset[2] = 4;
214 ctrl->timC_offset[0] = 11;
215 ctrl->timC_offset[1] = 4;
216 ctrl->timC_offset[2] = 4;
Angel Pons88521882020-01-05 20:21:20 +0100217 ctrl->pi_coding_threshold = 16;
Angel Pons7c49cb82020-03-16 23:17:32 +0100218
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200219 } else if (ctrl->tCK == TCK_533MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100220 ctrl->edge_offset[0] = 8;
221 ctrl->edge_offset[1] = 3;
222 ctrl->edge_offset[2] = 3;
223 ctrl->timC_offset[0] = 9;
224 ctrl->timC_offset[1] = 3;
225 ctrl->timC_offset[2] = 3;
Angel Pons88521882020-01-05 20:21:20 +0100226 ctrl->pi_coding_threshold = 17;
Angel Pons7c49cb82020-03-16 23:17:32 +0100227
Patrick Rudolph305035c2016-11-11 18:38:50 +0100228 } else {
229 ctrl->tCK = TCK_400MHZ;
230 ctrl->edge_offset[0] = 6;
231 ctrl->edge_offset[1] = 2;
232 ctrl->edge_offset[2] = 2;
233 ctrl->timC_offset[0] = 6;
234 ctrl->timC_offset[1] = 2;
235 ctrl->timC_offset[2] = 2;
Angel Pons88521882020-01-05 20:21:20 +0100236 ctrl->pi_coding_threshold = 17;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100237 }
238
239 /* Initial phase between CLK/CMD pins */
Angel Pons88521882020-01-05 20:21:20 +0100240 ctrl->pi_code_offset = (256000 / ctrl->tCK) / 66;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100241
242 /* DLL_CONFIG_MDLL_W_TIMER */
Angel Pons88521882020-01-05 20:21:20 +0100243 ctrl->mdll_wake_delay = (128000 / ctrl->tCK) + 3;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100244
Dan Elkoubydabebc32018-04-13 18:47:10 +0300245 if (ctrl->tCWL)
246 ctrl->CWL = DIV_ROUND_UP(ctrl->tCWL, ctrl->tCK);
247 else
248 ctrl->CWL = get_CWL(ctrl->tCK);
Angel Pons7c49cb82020-03-16 23:17:32 +0100249
Patrick Rudolph305035c2016-11-11 18:38:50 +0100250 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
251
252 /* Find tRCD */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100253 ctrl->tRCD = DIV_ROUND_UP(ctrl->tRCD, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100254 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
255
Angel Pons7c49cb82020-03-16 23:17:32 +0100256 ctrl->tRP = DIV_ROUND_UP(ctrl->tRP, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100257 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
258
259 /* Find tRAS */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100260 ctrl->tRAS = DIV_ROUND_UP(ctrl->tRAS, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100261 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
262
263 /* Find tWR */
Angel Pons7c49cb82020-03-16 23:17:32 +0100264 ctrl->tWR = DIV_ROUND_UP(ctrl->tWR, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100265 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
266
267 /* Find tFAW */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100268 ctrl->tFAW = DIV_ROUND_UP(ctrl->tFAW, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100269 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
270
271 /* Find tRRD */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100272 ctrl->tRRD = DIV_ROUND_UP(ctrl->tRRD, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100273 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
274
275 /* Find tRTP */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100276 ctrl->tRTP = DIV_ROUND_UP(ctrl->tRTP, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100277 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
278
279 /* Find tWTR */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100280 ctrl->tWTR = DIV_ROUND_UP(ctrl->tWTR, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100281 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
282
283 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
Angel Pons143309f2020-03-21 21:38:16 +0100284 ctrl->tRFC = DIV_ROUND_UP(ctrl->tRFC, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100285 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
286
Angel Pons7c49cb82020-03-16 23:17:32 +0100287 ctrl->tREFI = get_REFI(ctrl->tCK);
288 ctrl->tMOD = get_MOD(ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100289 ctrl->tXSOffset = get_XSOffset(ctrl->tCK);
Angel Pons7c49cb82020-03-16 23:17:32 +0100290 ctrl->tWLO = get_WLO(ctrl->tCK);
291 ctrl->tCKE = get_CKE(ctrl->tCK);
292 ctrl->tXPDLL = get_XPDLL(ctrl->tCK);
293 ctrl->tXP = get_XP(ctrl->tCK);
294 ctrl->tAONPD = get_AONPD(ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100295}
296
Angel Pons88521882020-01-05 20:21:20 +0100297static void dram_freq(ramctr_timing *ctrl)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100298{
299 if (ctrl->tCK > TCK_400MHZ) {
Angel Pons7c49cb82020-03-16 23:17:32 +0100300 printk(BIOS_ERR,
301 "DRAM frequency is under lowest supported frequency (400 MHz). "
302 "Increasing to 400 MHz as last resort");
Patrick Rudolph305035c2016-11-11 18:38:50 +0100303 ctrl->tCK = TCK_400MHZ;
304 }
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200305
Patrick Rudolph305035c2016-11-11 18:38:50 +0100306 while (1) {
307 u8 val2;
308 u32 reg1 = 0;
309
Angel Pons7c49cb82020-03-16 23:17:32 +0100310 /* Step 1 - Set target PCU frequency */
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200311 find_cas_tck(ctrl);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100312
Angel Pons7c49cb82020-03-16 23:17:32 +0100313 /* Frequency multiplier */
314 const u32 FRQ = get_FRQ(ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100315
Angel Pons7c49cb82020-03-16 23:17:32 +0100316 /*
317 * The PLL will never lock if the required frequency is already set.
318 * Exit early to prevent a system hang.
Patrick Rudolph305035c2016-11-11 18:38:50 +0100319 */
320 reg1 = MCHBAR32(MC_BIOS_DATA);
321 val2 = (u8) reg1;
322 if (val2)
323 return;
324
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200325 /* Step 1 - Select frequency in the MCU */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100326 reg1 = FRQ;
Angel Pons7c49cb82020-03-16 23:17:32 +0100327 reg1 |= 0x80000000; /* set running bit */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100328 MCHBAR32(MC_BIOS_REQ) = reg1;
329 int i=0;
330 printk(BIOS_DEBUG, "PLL busy... ");
331 while (reg1 & 0x80000000) {
332 udelay(10);
333 i++;
334 reg1 = MCHBAR32(MC_BIOS_REQ);
335 }
336 printk(BIOS_DEBUG, "done in %d us\n", i * 10);
337
Arthur Heymansdcd3cef2017-05-16 17:58:25 +0200338 /* Step 2 - Verify lock frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100339 reg1 = MCHBAR32(MC_BIOS_DATA);
340 val2 = (u8) reg1;
341 if (val2 >= FRQ) {
342 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
343 (1000 << 8) / ctrl->tCK);
344 return;
345 }
346 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
347 ctrl->tCK++;
348 }
349}
350
Angel Pons88521882020-01-05 20:21:20 +0100351static void dram_ioregs(ramctr_timing *ctrl)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100352{
Angel Pons7c49cb82020-03-16 23:17:32 +0100353 u32 reg;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100354
355 int channel;
356
Angel Pons7c49cb82020-03-16 23:17:32 +0100357 /* IO clock */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100358 FOR_ALL_CHANNELS {
Angel Pons88521882020-01-05 20:21:20 +0100359 MCHBAR32(GDCRCLKRANKSUSED_ch(channel)) = ctrl->rankmap[channel];
Patrick Rudolph305035c2016-11-11 18:38:50 +0100360 }
361
Angel Pons7c49cb82020-03-16 23:17:32 +0100362 /* IO command */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100363 FOR_ALL_CHANNELS {
Angel Pons88521882020-01-05 20:21:20 +0100364 MCHBAR32(GDCRCTLRANKSUSED_ch(channel)) = ctrl->rankmap[channel];
Patrick Rudolph305035c2016-11-11 18:38:50 +0100365 }
366
Angel Pons7c49cb82020-03-16 23:17:32 +0100367 /* IO control */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100368 FOR_ALL_POPULATED_CHANNELS {
369 program_timings(ctrl, channel);
370 }
371
Angel Pons7c49cb82020-03-16 23:17:32 +0100372 /* Perform RCOMP */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100373 printram("RCOMP...");
Angel Pons7c49cb82020-03-16 23:17:32 +0100374 while (!(MCHBAR32(RCOMP_TIMER) & (1 << 16)))
375 ;
376
Patrick Rudolph305035c2016-11-11 18:38:50 +0100377 printram("done\n");
378
Angel Pons7c49cb82020-03-16 23:17:32 +0100379 /* Set COMP2 */
380 MCHBAR32(CRCOMPOFST2) = get_COMP2(ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100381 printram("COMP2 done\n");
382
Angel Pons7c49cb82020-03-16 23:17:32 +0100383 /* Set COMP1 */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100384 FOR_ALL_POPULATED_CHANNELS {
Angel Pons7c49cb82020-03-16 23:17:32 +0100385 reg = MCHBAR32(CRCOMPOFST1_ch(channel));
386 reg = (reg & ~0x00000e00) | (1 << 9); /* ODT */
387 reg = (reg & ~0x00e00000) | (1 << 21); /* clk drive up */
388 reg = (reg & ~0x38000000) | (1 << 27); /* ctl drive up */
Angel Pons88521882020-01-05 20:21:20 +0100389 MCHBAR32(CRCOMPOFST1_ch(channel)) = reg;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100390 }
391 printram("COMP1 done\n");
392
393 printram("FORCE RCOMP and wait 20us...");
Angel Pons7c49cb82020-03-16 23:17:32 +0100394 MCHBAR32(M_COMP) |= (1 << 8);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100395 udelay(20);
396 printram("done\n");
397}
398
Angel Pons7c49cb82020-03-16 23:17:32 +0100399int try_init_dram_ddr3_snb(ramctr_timing *ctrl, int fast_boot, int s3_resume, int me_uma_size)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100400{
401 int err;
402
Angel Pons7c49cb82020-03-16 23:17:32 +0100403 printk(BIOS_DEBUG, "Starting SandyBridge RAM training (%d).\n", fast_boot);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100404
405 if (!fast_boot) {
406 /* Find fastest common supported parameters */
407 dram_find_common_params(ctrl);
408
409 dram_dimm_mapping(ctrl);
410 }
411
Angel Pons7c49cb82020-03-16 23:17:32 +0100412 /* Set MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100413 dram_freq(ctrl);
414
415 if (!fast_boot) {
416 /* Calculate timings */
417 dram_timing(ctrl);
418 }
419
420 /* Set version register */
Angel Pons7c49cb82020-03-16 23:17:32 +0100421 MCHBAR32(MRC_REVISION) = 0xc04eb002;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100422
423 /* Enable crossover */
424 dram_xover(ctrl);
425
426 /* Set timing and refresh registers */
427 dram_timing_regs(ctrl);
428
429 /* Power mode preset */
Angel Pons88521882020-01-05 20:21:20 +0100430 MCHBAR32(PM_THML_STAT) = 0x5500;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100431
Angel Pons88521882020-01-05 20:21:20 +0100432 /* Set scheduler chicken bits */
433 MCHBAR32(SCHED_CBIT) = 0x10100005;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100434
Angel Pons7c49cb82020-03-16 23:17:32 +0100435 /* Set up watermarks and starvation counter */
Angel Pons89ae6b82020-03-21 13:23:32 +0100436 set_wmm_behavior(ctrl->cpu);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100437
438 /* Clear IO reset bit */
Angel Pons7c49cb82020-03-16 23:17:32 +0100439 MCHBAR32(MC_INIT_STATE_G) &= ~(1 << 5);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100440
441 /* Set MAD-DIMM registers */
442 dram_dimm_set_mapping(ctrl);
443 printk(BIOS_DEBUG, "Done dimm mapping\n");
444
445 /* Zone config */
446 dram_zones(ctrl, 1);
447
448 /* Set memory map */
449 dram_memorymap(ctrl, me_uma_size);
450 printk(BIOS_DEBUG, "Done memory map\n");
451
452 /* Set IO registers */
453 dram_ioregs(ctrl);
454 printk(BIOS_DEBUG, "Done io registers\n");
455
456 udelay(1);
457
458 if (fast_boot) {
459 restore_timings(ctrl);
460 } else {
Angel Pons7c49cb82020-03-16 23:17:32 +0100461 /* Do JEDEC DDR3 reset sequence */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100462 dram_jedecreset(ctrl);
463 printk(BIOS_DEBUG, "Done jedec reset\n");
464
465 /* MRS commands */
466 dram_mrscommands(ctrl);
467 printk(BIOS_DEBUG, "Done MRS commands\n");
468
469 /* Prepare for memory training */
470 prepare_training(ctrl);
471
472 err = read_training(ctrl);
473 if (err)
474 return err;
475
476 err = write_training(ctrl);
477 if (err)
478 return err;
479
480 printram("CP5a\n");
481
482 err = discover_edges(ctrl);
483 if (err)
484 return err;
485
486 printram("CP5b\n");
487
488 err = command_training(ctrl);
489 if (err)
490 return err;
491
492 printram("CP5c\n");
493
494 err = discover_edges_write(ctrl);
495 if (err)
496 return err;
497
498 err = discover_timC_write(ctrl);
499 if (err)
500 return err;
501
502 normalize_training(ctrl);
503 }
504
Angel Pons7c49cb82020-03-16 23:17:32 +0100505 set_read_write_timings(ctrl);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100506
507 write_controller_mr(ctrl);
508
509 if (!s3_resume) {
510 err = channel_test(ctrl);
511 if (err)
512 return err;
513 }
514
515 return 0;
516}