blob: 832391f72e1318f6bab843c59ca1b85e73e42e00 [file] [log] [blame]
Angel Pons6e5aabd2020-03-23 23:44:42 +01001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Patrick Rudolph305035c2016-11-11 18:38:50 +01003
Angel Ponsa6c8b4b2020-03-23 22:38:08 +01004#include <commonlib/clamp.h>
Patrick Rudolph305035c2016-11-11 18:38:50 +01005#include <console/console.h>
6#include <console/usb.h>
Patrick Rudolph305035c2016-11-11 18:38:50 +01007#include <delay.h>
Angel Ponsfc930242020-03-24 11:12:09 +01008#include <device/device.h>
9#include <device/pci_def.h>
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +010010#include <device/pci_ops.h>
Angel Ponsfc930242020-03-24 11:12:09 +010011#include <northbridge/intel/sandybridge/chip.h>
Patrick Rudolph305035c2016-11-11 18:38:50 +010012#include "raminit_native.h"
13#include "raminit_common.h"
Angel Pons825332d2020-03-21 19:31:53 +010014#include "raminit_tables.h"
Patrick Rudolph305035c2016-11-11 18:38:50 +010015
Angel Ponsefbed262020-03-23 23:18:03 +010016#define SNB_MIN_DCLK_133_MULT 3
17#define SNB_MAX_DCLK_133_MULT 8
Angel Ponsa6c8b4b2020-03-23 22:38:08 +010018#define IVB_MIN_DCLK_133_MULT 3
19#define IVB_MAX_DCLK_133_MULT 10
20#define IVB_MIN_DCLK_100_MULT 7
21#define IVB_MAX_DCLK_100_MULT 12
Patrick Rudolph77eaba32016-11-11 18:55:54 +010022
Angel Ponsa6c8b4b2020-03-23 22:38:08 +010023/* Frequency multiplier */
24static u32 get_FRQ(const ramctr_timing *ctrl)
25{
26 const u32 FRQ = 256000 / (ctrl->tCK * ctrl->base_freq);
27
28 if (IS_IVY_CPU(ctrl->cpu)) {
29 if (ctrl->base_freq == 100)
30 return clamp_u32(IVB_MIN_DCLK_100_MULT, FRQ, IVB_MAX_DCLK_100_MULT);
31
32 if (ctrl->base_freq == 133)
33 return clamp_u32(IVB_MIN_DCLK_133_MULT, FRQ, IVB_MAX_DCLK_133_MULT);
Angel Ponsefbed262020-03-23 23:18:03 +010034
35 } else if (IS_SANDY_CPU(ctrl->cpu)) {
36 if (ctrl->base_freq == 133)
37 return clamp_u32(SNB_MIN_DCLK_133_MULT, FRQ, SNB_MAX_DCLK_133_MULT);
Patrick Rudolph77eaba32016-11-11 18:55:54 +010038 }
39
Angel Ponsa6c8b4b2020-03-23 22:38:08 +010040 die("Unsupported CPU or base frequency.");
Patrick Rudolph305035c2016-11-11 18:38:50 +010041}
42
Angel Ponsdf09bdb2020-03-21 16:40:41 +010043/* Get REFI based on frequency index, tREFI = 7.8usec */
44static u32 get_REFI(u32 FRQ, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +010045{
Angel Pons825332d2020-03-21 19:31:53 +010046 if (base_freq == 100)
Angel Ponsdf09bdb2020-03-21 16:40:41 +010047 return frq_refi_map[1][FRQ - 7];
Patrick Rudolph77eaba32016-11-11 18:55:54 +010048
Angel Pons825332d2020-03-21 19:31:53 +010049 else
Angel Ponsdf09bdb2020-03-21 16:40:41 +010050 return frq_refi_map[0][FRQ - 3];
Patrick Rudolph305035c2016-11-11 18:38:50 +010051}
52
Angel Ponsdf09bdb2020-03-21 16:40:41 +010053/* Get XSOffset based on frequency index, tXS-Offset: tXS = tRFC + 10ns */
54static u8 get_XSOffset(u32 FRQ, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +010055{
Angel Pons825332d2020-03-21 19:31:53 +010056 if (base_freq == 100)
Angel Ponsdf09bdb2020-03-21 16:40:41 +010057 return frq_xs_map[1][FRQ - 7];
Patrick Rudolph77eaba32016-11-11 18:55:54 +010058
Angel Pons825332d2020-03-21 19:31:53 +010059 else
Angel Ponsdf09bdb2020-03-21 16:40:41 +010060 return frq_xs_map[0][FRQ - 3];
Patrick Rudolph305035c2016-11-11 18:38:50 +010061}
62
Angel Ponsdf09bdb2020-03-21 16:40:41 +010063/* Get MOD based on frequency index */
64static u8 get_MOD(u32 FRQ, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +010065{
Angel Pons825332d2020-03-21 19:31:53 +010066 if (base_freq == 100)
Angel Ponsdf09bdb2020-03-21 16:40:41 +010067 return frq_mod_map[1][FRQ - 7];
Patrick Rudolph77eaba32016-11-11 18:55:54 +010068
Angel Pons825332d2020-03-21 19:31:53 +010069 else
Angel Ponsdf09bdb2020-03-21 16:40:41 +010070 return frq_mod_map[0][FRQ - 3];
Patrick Rudolph305035c2016-11-11 18:38:50 +010071}
72
Angel Ponsdf09bdb2020-03-21 16:40:41 +010073/* Get Write Leveling Output delay based on frequency index */
74static u8 get_WLO(u32 FRQ, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +010075{
Angel Pons825332d2020-03-21 19:31:53 +010076 if (base_freq == 100)
Angel Ponsdf09bdb2020-03-21 16:40:41 +010077 return frq_wlo_map[1][FRQ - 7];
Patrick Rudolph77eaba32016-11-11 18:55:54 +010078
Angel Pons825332d2020-03-21 19:31:53 +010079 else
Angel Ponsdf09bdb2020-03-21 16:40:41 +010080 return frq_wlo_map[0][FRQ - 3];
Patrick Rudolph305035c2016-11-11 18:38:50 +010081}
82
Angel Ponsdf09bdb2020-03-21 16:40:41 +010083/* Get CKE based on frequency index */
84static u8 get_CKE(u32 FRQ, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +010085{
Angel Pons825332d2020-03-21 19:31:53 +010086 if (base_freq == 100)
Angel Ponsdf09bdb2020-03-21 16:40:41 +010087 return frq_cke_map[1][FRQ - 7];
Patrick Rudolph77eaba32016-11-11 18:55:54 +010088
Angel Pons825332d2020-03-21 19:31:53 +010089 else
Angel Ponsdf09bdb2020-03-21 16:40:41 +010090 return frq_cke_map[0][FRQ - 3];
Patrick Rudolph305035c2016-11-11 18:38:50 +010091}
92
Angel Ponsdf09bdb2020-03-21 16:40:41 +010093/* Get XPDLL based on frequency index */
94static u8 get_XPDLL(u32 FRQ, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +010095{
Angel Pons825332d2020-03-21 19:31:53 +010096 if (base_freq == 100)
Angel Ponsdf09bdb2020-03-21 16:40:41 +010097 return frq_xpdll_map[1][FRQ - 7];
Patrick Rudolph77eaba32016-11-11 18:55:54 +010098
Angel Pons825332d2020-03-21 19:31:53 +010099 else
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100100 return frq_xpdll_map[0][FRQ - 3];
Patrick Rudolph305035c2016-11-11 18:38:50 +0100101}
102
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100103/* Get XP based on frequency index */
104static u8 get_XP(u32 FRQ, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100105{
Angel Pons825332d2020-03-21 19:31:53 +0100106 if (base_freq == 100)
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100107 return frq_xp_map[1][FRQ - 7];
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100108
Angel Pons825332d2020-03-21 19:31:53 +0100109 else
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100110 return frq_xp_map[0][FRQ - 3];
Patrick Rudolph305035c2016-11-11 18:38:50 +0100111}
112
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100113/* Get AONPD based on frequency index */
114static u8 get_AONPD(u32 FRQ, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100115{
Angel Pons825332d2020-03-21 19:31:53 +0100116 if (base_freq == 100)
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100117 return frq_aonpd_map[1][FRQ - 7];
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100118
Angel Pons825332d2020-03-21 19:31:53 +0100119 else
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100120 return frq_aonpd_map[0][FRQ - 3];
Patrick Rudolph305035c2016-11-11 18:38:50 +0100121}
122
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100123/* Get COMP2 based on frequency index */
124static u32 get_COMP2(u32 FRQ, u8 base_freq)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100125{
Angel Pons825332d2020-03-21 19:31:53 +0100126 if (base_freq == 100)
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100127 return frq_comp2_map[1][FRQ - 7];
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100128
Angel Pons825332d2020-03-21 19:31:53 +0100129 else
Angel Ponsdf09bdb2020-03-21 16:40:41 +0100130 return frq_comp2_map[0][FRQ - 3];
Patrick Rudolph305035c2016-11-11 18:38:50 +0100131}
132
Angel Ponsefbed262020-03-23 23:18:03 +0100133static void normalize_tclk(ramctr_timing *ctrl, bool ref_100mhz_support)
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200134{
135 if (ctrl->tCK <= TCK_1200MHZ) {
136 ctrl->tCK = TCK_1200MHZ;
137 ctrl->base_freq = 100;
138 } else if (ctrl->tCK <= TCK_1100MHZ) {
139 ctrl->tCK = TCK_1100MHZ;
140 ctrl->base_freq = 100;
141 } else if (ctrl->tCK <= TCK_1066MHZ) {
142 ctrl->tCK = TCK_1066MHZ;
143 ctrl->base_freq = 133;
144 } else if (ctrl->tCK <= TCK_1000MHZ) {
145 ctrl->tCK = TCK_1000MHZ;
146 ctrl->base_freq = 100;
147 } else if (ctrl->tCK <= TCK_933MHZ) {
148 ctrl->tCK = TCK_933MHZ;
149 ctrl->base_freq = 133;
150 } else if (ctrl->tCK <= TCK_900MHZ) {
151 ctrl->tCK = TCK_900MHZ;
152 ctrl->base_freq = 100;
153 } else if (ctrl->tCK <= TCK_800MHZ) {
154 ctrl->tCK = TCK_800MHZ;
155 ctrl->base_freq = 133;
156 } else if (ctrl->tCK <= TCK_700MHZ) {
157 ctrl->tCK = TCK_700MHZ;
158 ctrl->base_freq = 100;
159 } else if (ctrl->tCK <= TCK_666MHZ) {
160 ctrl->tCK = TCK_666MHZ;
161 ctrl->base_freq = 133;
162 } else if (ctrl->tCK <= TCK_533MHZ) {
163 ctrl->tCK = TCK_533MHZ;
164 ctrl->base_freq = 133;
165 } else if (ctrl->tCK <= TCK_400MHZ) {
166 ctrl->tCK = TCK_400MHZ;
167 ctrl->base_freq = 133;
168 } else {
169 ctrl->tCK = 0;
170 return;
171 }
172
173 if (!ref_100mhz_support && ctrl->base_freq == 100) {
Angel Pons7c49cb82020-03-16 23:17:32 +0100174 /* Skip unsupported frequency */
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200175 ctrl->tCK++;
Angel Ponsefbed262020-03-23 23:18:03 +0100176 normalize_tclk(ctrl, ref_100mhz_support);
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200177 }
178}
179
Angel Ponsfc930242020-03-24 11:12:09 +0100180#define DEFAULT_TCK TCK_800MHZ
181
182static unsigned int get_mem_min_tck(void)
183{
184 u32 reg32;
185 u8 rev;
186 const struct northbridge_intel_sandybridge_config *cfg = NULL;
187
188 /* Actually, config of MCH or Host Bridge */
189 cfg = config_of_soc();
190
191 /* If non-zero, it was set in the devicetree */
192 if (cfg->max_mem_clock_mhz) {
193
194 if (cfg->max_mem_clock_mhz >= 1066)
195 return TCK_1066MHZ;
196
197 else if (cfg->max_mem_clock_mhz >= 933)
198 return TCK_933MHZ;
199
200 else if (cfg->max_mem_clock_mhz >= 800)
201 return TCK_800MHZ;
202
203 else if (cfg->max_mem_clock_mhz >= 666)
204 return TCK_666MHZ;
205
206 else if (cfg->max_mem_clock_mhz >= 533)
207 return TCK_533MHZ;
208
209 else
210 return TCK_400MHZ;
211 }
212
213 if (CONFIG(NATIVE_RAMINIT_IGNORE_MAX_MEM_FUSES))
214 return TCK_1333MHZ;
215
216 rev = pci_read_config8(HOST_BRIDGE, PCI_DEVICE_ID);
217
218 if ((rev & BASE_REV_MASK) == BASE_REV_SNB) {
219 /* Read Capabilities A Register DMFC bits */
220 reg32 = pci_read_config32(HOST_BRIDGE, CAPID0_A);
221 reg32 &= 0x7;
222
223 switch (reg32) {
224 case 7: return TCK_533MHZ;
225 case 6: return TCK_666MHZ;
226 case 5: return TCK_800MHZ;
227 /* Reserved */
228 default:
229 break;
230 }
231 } else {
232 /* Read Capabilities B Register DMFC bits */
233 reg32 = pci_read_config32(HOST_BRIDGE, CAPID0_B);
234 reg32 = (reg32 >> 4) & 0x7;
235
236 switch (reg32) {
237 case 7: return TCK_533MHZ;
238 case 6: return TCK_666MHZ;
239 case 5: return TCK_800MHZ;
240 case 4: return TCK_933MHZ;
241 case 3: return TCK_1066MHZ;
242 case 2: return TCK_1200MHZ;
243 case 1: return TCK_1333MHZ;
244 /* Reserved */
245 default:
246 break;
247 }
248 }
249 return DEFAULT_TCK;
250}
251
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200252static void find_cas_tck(ramctr_timing *ctrl)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100253{
254 u8 val;
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200255 u32 reg32;
256 u8 ref_100mhz_support;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100257
Angel Pons7c49cb82020-03-16 23:17:32 +0100258 /* 100 MHz reference clock supported */
259 reg32 = pci_read_config32(HOST_BRIDGE, CAPID0_B);
Angel Pons29f391ec2020-03-23 22:51:05 +0100260 ref_100mhz_support = (reg32 >> 21) & 0x7;
Angel Pons7c49cb82020-03-16 23:17:32 +0100261 printk(BIOS_DEBUG, "100MHz reference clock support: %s\n", ref_100mhz_support ? "yes"
262 : "no");
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200263
Angel Pons29f391ec2020-03-23 22:51:05 +0100264 printk(BIOS_DEBUG, "PLL_REF100_CFG value: 0x%x\n", ref_100mhz_support);
265
Angel Ponsfc930242020-03-24 11:12:09 +0100266 ctrl->tCK = get_mem_min_tck();
267
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200268 /* Find CAS latency */
269 while (1) {
Angel Pons7c49cb82020-03-16 23:17:32 +0100270 /*
271 * Normalising tCK before computing clock could potentially
272 * result in a lower selected CAS, which is desired.
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200273 */
Angel Ponsefbed262020-03-23 23:18:03 +0100274 normalize_tclk(ctrl, ref_100mhz_support);
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200275 if (!(ctrl->tCK))
276 die("Couldn't find compatible clock / CAS settings\n");
Angel Pons7c49cb82020-03-16 23:17:32 +0100277
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200278 val = DIV_ROUND_UP(ctrl->tAA, ctrl->tCK);
279 printk(BIOS_DEBUG, "Trying CAS %u, tCK %u.\n", val, ctrl->tCK);
280 for (; val <= MAX_CAS; val++)
281 if ((ctrl->cas_supported >> (val - MIN_CAS)) & 1)
282 break;
Angel Pons7c49cb82020-03-16 23:17:32 +0100283
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200284 if (val == (MAX_CAS + 1)) {
285 ctrl->tCK++;
286 continue;
287 } else {
288 printk(BIOS_DEBUG, "Found compatible clock, CAS pair.\n");
289 break;
290 }
291 }
292
Angel Pons48409b82020-03-23 22:19:29 +0100293 /* Frequency multiplier */
Angel Ponsa6c8b4b2020-03-23 22:38:08 +0100294 ctrl->FRQ = get_FRQ(ctrl);
Angel Pons48409b82020-03-23 22:19:29 +0100295
Angel Pons7c49cb82020-03-16 23:17:32 +0100296 printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", NS2MHZ_DIV256 / ctrl->tCK);
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200297 printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", val);
298 ctrl->CAS = val;
299}
300
301
302static void dram_timing(ramctr_timing *ctrl)
303{
Angel Pons7c49cb82020-03-16 23:17:32 +0100304 /*
Angel Ponsefbed262020-03-23 23:18:03 +0100305 * On Sandy Bridge, the maximum supported DDR3 frequency is 1066MHz (DDR3 2133).
306 * Cap it for faster DIMMs, and align it to the closest JEDEC standard frequency.
307 */
308 /*
Angel Pons7c49cb82020-03-16 23:17:32 +0100309 * On Ivy Bridge, the maximum supported DDR3 frequency is 1400MHz (DDR3 2800).
310 * Cap it at 1200MHz (DDR3 2400), and align it to the closest JEDEC standard frequency.
311 */
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200312 if (ctrl->tCK == TCK_1200MHZ) {
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100313 ctrl->edge_offset[0] = 18; //XXX: guessed
314 ctrl->edge_offset[1] = 8;
315 ctrl->edge_offset[2] = 8;
316 ctrl->timC_offset[0] = 20; //XXX: guessed
317 ctrl->timC_offset[1] = 8;
318 ctrl->timC_offset[2] = 8;
Angel Pons88521882020-01-05 20:21:20 +0100319 ctrl->pi_coding_threshold = 10;
Angel Pons7c49cb82020-03-16 23:17:32 +0100320
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200321 } else if (ctrl->tCK == TCK_1100MHZ) {
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100322 ctrl->edge_offset[0] = 17; //XXX: guessed
323 ctrl->edge_offset[1] = 7;
324 ctrl->edge_offset[2] = 7;
325 ctrl->timC_offset[0] = 19; //XXX: guessed
326 ctrl->timC_offset[1] = 7;
327 ctrl->timC_offset[2] = 7;
Angel Pons88521882020-01-05 20:21:20 +0100328 ctrl->pi_coding_threshold = 13;
Angel Pons7c49cb82020-03-16 23:17:32 +0100329
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200330 } else if (ctrl->tCK == TCK_1066MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100331 ctrl->edge_offset[0] = 16;
332 ctrl->edge_offset[1] = 7;
333 ctrl->edge_offset[2] = 7;
334 ctrl->timC_offset[0] = 18;
335 ctrl->timC_offset[1] = 7;
336 ctrl->timC_offset[2] = 7;
Angel Pons88521882020-01-05 20:21:20 +0100337 ctrl->pi_coding_threshold = 13;
Angel Pons7c49cb82020-03-16 23:17:32 +0100338
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200339 } else if (ctrl->tCK == TCK_1000MHZ) {
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100340 ctrl->edge_offset[0] = 15; //XXX: guessed
341 ctrl->edge_offset[1] = 6;
342 ctrl->edge_offset[2] = 6;
343 ctrl->timC_offset[0] = 17; //XXX: guessed
344 ctrl->timC_offset[1] = 6;
345 ctrl->timC_offset[2] = 6;
Angel Pons88521882020-01-05 20:21:20 +0100346 ctrl->pi_coding_threshold = 13;
Angel Pons7c49cb82020-03-16 23:17:32 +0100347
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200348 } else if (ctrl->tCK == TCK_933MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100349 ctrl->edge_offset[0] = 14;
350 ctrl->edge_offset[1] = 6;
351 ctrl->edge_offset[2] = 6;
352 ctrl->timC_offset[0] = 15;
353 ctrl->timC_offset[1] = 6;
354 ctrl->timC_offset[2] = 6;
Angel Pons88521882020-01-05 20:21:20 +0100355 ctrl->pi_coding_threshold = 15;
Angel Pons7c49cb82020-03-16 23:17:32 +0100356
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200357 } else if (ctrl->tCK == TCK_900MHZ) {
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100358 ctrl->edge_offset[0] = 14; //XXX: guessed
359 ctrl->edge_offset[1] = 6;
360 ctrl->edge_offset[2] = 6;
361 ctrl->timC_offset[0] = 15; //XXX: guessed
362 ctrl->timC_offset[1] = 6;
363 ctrl->timC_offset[2] = 6;
Angel Pons88521882020-01-05 20:21:20 +0100364 ctrl->pi_coding_threshold = 12;
Angel Pons7c49cb82020-03-16 23:17:32 +0100365
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200366 } else if (ctrl->tCK == TCK_800MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100367 ctrl->edge_offset[0] = 13;
368 ctrl->edge_offset[1] = 5;
369 ctrl->edge_offset[2] = 5;
370 ctrl->timC_offset[0] = 14;
371 ctrl->timC_offset[1] = 5;
372 ctrl->timC_offset[2] = 5;
Angel Pons88521882020-01-05 20:21:20 +0100373 ctrl->pi_coding_threshold = 15;
Angel Pons7c49cb82020-03-16 23:17:32 +0100374
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200375 } else if (ctrl->tCK == TCK_700MHZ) {
Patrick Rudolphcb7d6a12016-11-25 15:40:49 +0100376 ctrl->edge_offset[0] = 13; //XXX: guessed
377 ctrl->edge_offset[1] = 5;
378 ctrl->edge_offset[2] = 5;
379 ctrl->timC_offset[0] = 14; //XXX: guessed
380 ctrl->timC_offset[1] = 5;
381 ctrl->timC_offset[2] = 5;
Angel Pons88521882020-01-05 20:21:20 +0100382 ctrl->pi_coding_threshold = 16;
Angel Pons7c49cb82020-03-16 23:17:32 +0100383
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200384 } else if (ctrl->tCK == TCK_666MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100385 ctrl->edge_offset[0] = 10;
386 ctrl->edge_offset[1] = 4;
387 ctrl->edge_offset[2] = 4;
388 ctrl->timC_offset[0] = 11;
389 ctrl->timC_offset[1] = 4;
390 ctrl->timC_offset[2] = 4;
Angel Pons88521882020-01-05 20:21:20 +0100391 ctrl->pi_coding_threshold = 16;
Angel Pons7c49cb82020-03-16 23:17:32 +0100392
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200393 } else if (ctrl->tCK == TCK_533MHZ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100394 ctrl->edge_offset[0] = 8;
395 ctrl->edge_offset[1] = 3;
396 ctrl->edge_offset[2] = 3;
397 ctrl->timC_offset[0] = 9;
398 ctrl->timC_offset[1] = 3;
399 ctrl->timC_offset[2] = 3;
Angel Pons88521882020-01-05 20:21:20 +0100400 ctrl->pi_coding_threshold = 17;
Angel Pons7c49cb82020-03-16 23:17:32 +0100401
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200402 } else { /* TCK_400MHZ */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100403 ctrl->edge_offset[0] = 6;
404 ctrl->edge_offset[1] = 2;
405 ctrl->edge_offset[2] = 2;
406 ctrl->timC_offset[0] = 6;
407 ctrl->timC_offset[1] = 2;
408 ctrl->timC_offset[2] = 2;
Angel Pons88521882020-01-05 20:21:20 +0100409 ctrl->pi_coding_threshold = 17;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100410 }
411
412 /* Initial phase between CLK/CMD pins */
Angel Pons88521882020-01-05 20:21:20 +0100413 ctrl->pi_code_offset = (256000 / ctrl->tCK) / 66;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100414
415 /* DLL_CONFIG_MDLL_W_TIMER */
Angel Pons88521882020-01-05 20:21:20 +0100416 ctrl->mdll_wake_delay = (128000 / ctrl->tCK) + 3;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100417
Dan Elkoubydabebc32018-04-13 18:47:10 +0300418 if (ctrl->tCWL)
419 ctrl->CWL = DIV_ROUND_UP(ctrl->tCWL, ctrl->tCK);
420 else
421 ctrl->CWL = get_CWL(ctrl->tCK);
Angel Pons7c49cb82020-03-16 23:17:32 +0100422
Patrick Rudolph305035c2016-11-11 18:38:50 +0100423 printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL);
424
425 /* Find tRCD */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100426 ctrl->tRCD = DIV_ROUND_UP(ctrl->tRCD, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100427 printk(BIOS_DEBUG, "Selected tRCD : %uT\n", ctrl->tRCD);
428
Angel Pons7c49cb82020-03-16 23:17:32 +0100429 ctrl->tRP = DIV_ROUND_UP(ctrl->tRP, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100430 printk(BIOS_DEBUG, "Selected tRP : %uT\n", ctrl->tRP);
431
432 /* Find tRAS */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100433 ctrl->tRAS = DIV_ROUND_UP(ctrl->tRAS, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100434 printk(BIOS_DEBUG, "Selected tRAS : %uT\n", ctrl->tRAS);
435
436 /* Find tWR */
Angel Pons7c49cb82020-03-16 23:17:32 +0100437 ctrl->tWR = DIV_ROUND_UP(ctrl->tWR, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100438 printk(BIOS_DEBUG, "Selected tWR : %uT\n", ctrl->tWR);
439
440 /* Find tFAW */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100441 ctrl->tFAW = DIV_ROUND_UP(ctrl->tFAW, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100442 printk(BIOS_DEBUG, "Selected tFAW : %uT\n", ctrl->tFAW);
443
444 /* Find tRRD */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100445 ctrl->tRRD = DIV_ROUND_UP(ctrl->tRRD, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100446 printk(BIOS_DEBUG, "Selected tRRD : %uT\n", ctrl->tRRD);
447
448 /* Find tRTP */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100449 ctrl->tRTP = DIV_ROUND_UP(ctrl->tRTP, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100450 printk(BIOS_DEBUG, "Selected tRTP : %uT\n", ctrl->tRTP);
451
452 /* Find tWTR */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100453 ctrl->tWTR = DIV_ROUND_UP(ctrl->tWTR, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100454 printk(BIOS_DEBUG, "Selected tWTR : %uT\n", ctrl->tWTR);
455
456 /* Refresh-to-Active or Refresh-to-Refresh (tRFC) */
Arthur Heymans50db9c92017-03-23 18:53:38 +0100457 ctrl->tRFC = DIV_ROUND_UP(ctrl->tRFC, ctrl->tCK);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100458 printk(BIOS_DEBUG, "Selected tRFC : %uT\n", ctrl->tRFC);
459
Angel Pons48409b82020-03-23 22:19:29 +0100460 ctrl->tREFI = get_REFI(ctrl->FRQ, ctrl->base_freq);
461 ctrl->tMOD = get_MOD(ctrl->FRQ, ctrl->base_freq);
462 ctrl->tXSOffset = get_XSOffset(ctrl->FRQ, ctrl->base_freq);
463 ctrl->tWLO = get_WLO(ctrl->FRQ, ctrl->base_freq);
464 ctrl->tCKE = get_CKE(ctrl->FRQ, ctrl->base_freq);
465 ctrl->tXPDLL = get_XPDLL(ctrl->FRQ, ctrl->base_freq);
466 ctrl->tXP = get_XP(ctrl->FRQ, ctrl->base_freq);
467 ctrl->tAONPD = get_AONPD(ctrl->FRQ, ctrl->base_freq);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100468}
469
Angel Pons88521882020-01-05 20:21:20 +0100470static void dram_freq(ramctr_timing *ctrl)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100471{
472 if (ctrl->tCK > TCK_400MHZ) {
Angel Pons7c49cb82020-03-16 23:17:32 +0100473 printk(BIOS_ERR,
474 "DRAM frequency is under lowest supported frequency (400 MHz). "
475 "Increasing to 400 MHz as last resort");
Patrick Rudolph305035c2016-11-11 18:38:50 +0100476 ctrl->tCK = TCK_400MHZ;
477 }
Patrick Rudolph77eaba32016-11-11 18:55:54 +0100478
Patrick Rudolph305035c2016-11-11 18:38:50 +0100479 while (1) {
480 u8 val2;
481 u32 reg1 = 0;
482
483 /* Step 1 - Set target PCU frequency */
Arthur Heymans9ed74b52017-05-16 19:56:49 +0200484 find_cas_tck(ctrl);
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100485
Angel Pons7c49cb82020-03-16 23:17:32 +0100486 /*
487 * The PLL will never lock if the required frequency is already set.
488 * Exit early to prevent a system hang.
Patrick Rudolph305035c2016-11-11 18:38:50 +0100489 */
490 reg1 = MCHBAR32(MC_BIOS_DATA);
491 val2 = (u8) reg1;
492 if (val2)
493 return;
494
495 /* Step 2 - Select frequency in the MCU */
Angel Pons48409b82020-03-23 22:19:29 +0100496 reg1 = ctrl->FRQ;
Patrick Rudolphcab4d3d2016-11-24 19:40:23 +0100497 if (ctrl->base_freq == 100)
Angel Pons7c49cb82020-03-16 23:17:32 +0100498 reg1 |= 0x100; /* Enable 100Mhz REF clock */
499
500 reg1 |= 0x80000000; /* set running bit */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100501 MCHBAR32(MC_BIOS_REQ) = reg1;
Angel Pons7c49cb82020-03-16 23:17:32 +0100502 int i = 0;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100503 printk(BIOS_DEBUG, "PLL busy... ");
504 while (reg1 & 0x80000000) {
505 udelay(10);
506 i++;
507 reg1 = MCHBAR32(MC_BIOS_REQ);
508 }
509 printk(BIOS_DEBUG, "done in %d us\n", i * 10);
510
511 /* Step 3 - Verify lock frequency */
512 reg1 = MCHBAR32(MC_BIOS_DATA);
513 val2 = (u8) reg1;
Angel Pons48409b82020-03-23 22:19:29 +0100514 if (val2 >= ctrl->FRQ) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100515 printk(BIOS_DEBUG, "MCU frequency is set at : %d MHz\n",
516 (1000 << 8) / ctrl->tCK);
517 return;
518 }
519 printk(BIOS_DEBUG, "PLL didn't lock. Retrying at lower frequency\n");
520 ctrl->tCK++;
521 }
522}
523
Angel Pons88521882020-01-05 20:21:20 +0100524static void dram_ioregs(ramctr_timing *ctrl)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100525{
Angel Pons7c49cb82020-03-16 23:17:32 +0100526 u32 reg;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100527
528 int channel;
529
Angel Pons7c49cb82020-03-16 23:17:32 +0100530 /* IO clock */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100531 FOR_ALL_CHANNELS {
Angel Pons88521882020-01-05 20:21:20 +0100532 MCHBAR32(GDCRCLKRANKSUSED_ch(channel)) = ctrl->rankmap[channel];
Patrick Rudolph305035c2016-11-11 18:38:50 +0100533 }
534
Angel Pons7c49cb82020-03-16 23:17:32 +0100535 /* IO command */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100536 FOR_ALL_CHANNELS {
Angel Pons88521882020-01-05 20:21:20 +0100537 MCHBAR32(GDCRCTLRANKSUSED_ch(channel)) = ctrl->rankmap[channel];
Patrick Rudolph305035c2016-11-11 18:38:50 +0100538 }
539
Angel Pons7c49cb82020-03-16 23:17:32 +0100540 /* IO control */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100541 FOR_ALL_POPULATED_CHANNELS {
542 program_timings(ctrl, channel);
543 }
544
Angel Pons7c49cb82020-03-16 23:17:32 +0100545 /* Perform RCOMP */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100546 printram("RCOMP...");
Angel Pons7c49cb82020-03-16 23:17:32 +0100547 while (!(MCHBAR32(RCOMP_TIMER) & (1 << 16)))
548 ;
549
Patrick Rudolph305035c2016-11-11 18:38:50 +0100550 printram("done\n");
551
Angel Pons7c49cb82020-03-16 23:17:32 +0100552 /* Set COMP2 */
Angel Pons48409b82020-03-23 22:19:29 +0100553 MCHBAR32(CRCOMPOFST2) = get_COMP2(ctrl->FRQ, ctrl->base_freq);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100554 printram("COMP2 done\n");
555
Angel Pons7c49cb82020-03-16 23:17:32 +0100556 /* Set COMP1 */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100557 FOR_ALL_POPULATED_CHANNELS {
Angel Pons7c49cb82020-03-16 23:17:32 +0100558 reg = MCHBAR32(CRCOMPOFST1_ch(channel));
559 reg = (reg & ~0x00000e00) | (1 << 9); /* ODT */
560 reg = (reg & ~0x00e00000) | (1 << 21); /* clk drive up */
561 reg = (reg & ~0x38000000) | (1 << 27); /* ctl drive up */
Angel Pons88521882020-01-05 20:21:20 +0100562 MCHBAR32(CRCOMPOFST1_ch(channel)) = reg;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100563 }
564 printram("COMP1 done\n");
565
566 printram("FORCE RCOMP and wait 20us...");
Angel Pons7c49cb82020-03-16 23:17:32 +0100567 MCHBAR32(M_COMP) |= (1 << 8);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100568 udelay(20);
569 printram("done\n");
570}
571
Angel Ponsefbed262020-03-23 23:18:03 +0100572int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot, int s3resume, int me_uma_size)
Patrick Rudolph305035c2016-11-11 18:38:50 +0100573{
574 int err;
575
Angel Ponsefbed262020-03-23 23:18:03 +0100576 printk(BIOS_DEBUG, "Starting %s Bridge RAM training (%s).\n",
577 IS_SANDY_CPU(ctrl->cpu) ? "Sandy" : "Ivy",
578 fast_boot ? "fast boot" : "full initialization");
Patrick Rudolph305035c2016-11-11 18:38:50 +0100579
580 if (!fast_boot) {
581 /* Find fastest common supported parameters */
582 dram_find_common_params(ctrl);
583
584 dram_dimm_mapping(ctrl);
585 }
586
Angel Pons7c49cb82020-03-16 23:17:32 +0100587 /* Set MC frequency */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100588 dram_freq(ctrl);
589
590 if (!fast_boot) {
591 /* Calculate timings */
592 dram_timing(ctrl);
593 }
594
595 /* Set version register */
Angel Pons7c49cb82020-03-16 23:17:32 +0100596 MCHBAR32(MRC_REVISION) = 0xc04eb002;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100597
598 /* Enable crossover */
599 dram_xover(ctrl);
600
601 /* Set timing and refresh registers */
602 dram_timing_regs(ctrl);
603
604 /* Power mode preset */
Angel Pons88521882020-01-05 20:21:20 +0100605 MCHBAR32(PM_THML_STAT) = 0x5500;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100606
Angel Pons88521882020-01-05 20:21:20 +0100607 /* Set scheduler chicken bits */
608 MCHBAR32(SCHED_CBIT) = 0x10100005;
Patrick Rudolph305035c2016-11-11 18:38:50 +0100609
Angel Pons7c49cb82020-03-16 23:17:32 +0100610 /* Set up watermarks and starvation counter */
Angel Pons89ae6b82020-03-21 13:23:32 +0100611 set_wmm_behavior(ctrl->cpu);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100612
613 /* Clear IO reset bit */
Angel Pons7c49cb82020-03-16 23:17:32 +0100614 MCHBAR32(MC_INIT_STATE_G) &= ~(1 << 5);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100615
616 /* Set MAD-DIMM registers */
Patrick Rudolphdd662872017-10-28 18:20:11 +0200617 dram_dimm_set_mapping(ctrl, 1);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100618 printk(BIOS_DEBUG, "Done dimm mapping\n");
619
620 /* Zone config */
621 dram_zones(ctrl, 1);
622
623 /* Set memory map */
624 dram_memorymap(ctrl, me_uma_size);
625 printk(BIOS_DEBUG, "Done memory map\n");
626
627 /* Set IO registers */
628 dram_ioregs(ctrl);
629 printk(BIOS_DEBUG, "Done io registers\n");
630
631 udelay(1);
632
633 if (fast_boot) {
634 restore_timings(ctrl);
635 } else {
Angel Pons7c49cb82020-03-16 23:17:32 +0100636 /* Do JEDEC DDR3 reset sequence */
Patrick Rudolph305035c2016-11-11 18:38:50 +0100637 dram_jedecreset(ctrl);
638 printk(BIOS_DEBUG, "Done jedec reset\n");
639
640 /* MRS commands */
641 dram_mrscommands(ctrl);
642 printk(BIOS_DEBUG, "Done MRS commands\n");
643
644 /* Prepare for memory training */
645 prepare_training(ctrl);
646
647 err = read_training(ctrl);
648 if (err)
649 return err;
650
651 err = write_training(ctrl);
652 if (err)
653 return err;
654
655 printram("CP5a\n");
656
657 err = discover_edges(ctrl);
658 if (err)
659 return err;
660
661 printram("CP5b\n");
662
663 err = command_training(ctrl);
664 if (err)
665 return err;
666
667 printram("CP5c\n");
668
669 err = discover_edges_write(ctrl);
670 if (err)
671 return err;
672
673 err = discover_timC_write(ctrl);
674 if (err)
675 return err;
676
677 normalize_training(ctrl);
678 }
679
Angel Pons7c49cb82020-03-16 23:17:32 +0100680 set_read_write_timings(ctrl);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100681
682 write_controller_mr(ctrl);
683
Angel Ponsefbed262020-03-23 23:18:03 +0100684 if (!s3resume) {
Patrick Rudolph305035c2016-11-11 18:38:50 +0100685 err = channel_test(ctrl);
686 if (err)
687 return err;
Patrick Rudolphdd662872017-10-28 18:20:11 +0200688
689 if (ctrl->ecc_enabled)
690 channel_scrub(ctrl);
Patrick Rudolph305035c2016-11-11 18:38:50 +0100691 }
692
Patrick Rudolphdd662872017-10-28 18:20:11 +0200693 /* Set MAD-DIMM registers */
694 dram_dimm_set_mapping(ctrl, 0);
695
Patrick Rudolph305035c2016-11-11 18:38:50 +0100696 return 0;
697}