coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
raminit_common.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #ifndef RAMINIT_COMMON_H
4 #define RAMINIT_COMMON_H
5 
6 #include <stdint.h>
7 
8 #define BASEFREQ 133
9 #define tDLLK 512
10 
11 #define NUM_CHANNELS 2
12 #define NUM_SLOTRANKS 4
13 #define NUM_SLOTS 2
14 #define NUM_LANES 9
15 
16 /* IOSAV_n_SP_CMD_CTRL DRAM commands */
17 #define IOSAV_MRS (0xf000)
18 #define IOSAV_PRE (0xf002)
19 #define IOSAV_ZQCS (0xf003)
20 #define IOSAV_ACT (0xf006)
21 #define IOSAV_RD (0xf105)
22 #define IOSAV_NOP_ALT (0xf107)
23 #define IOSAV_WR (0xf201)
24 #define IOSAV_NOP (0xf207)
25 
26 /* IOSAV_n_SUBSEQ_CTRL data direction */
27 #define SSQ_NA 0 /* Non-data */
28 #define SSQ_RD 1 /* Read */
29 #define SSQ_WR 2 /* Write */
30 #define SSQ_RW 3 /* Read and write */
31 
32 struct iosav_ssq {
33  /* IOSAV_n_SP_CMD_CTRL */
34  union {
35  struct {
36  u32 command : 16; /* [15.. 0] */
37  u32 ranksel_ap : 2; /* [17..16] */
38  u32 : 14;
39  };
42 
43  /* IOSAV_n_SUBSEQ_CTRL */
44  union {
45  struct {
46  u32 cmd_executions : 9; /* [ 8.. 0] */
47  u32 : 1;
48  u32 cmd_delay_gap : 5; /* [14..10] */
49  u32 : 1;
50  u32 post_ssq_wait : 9; /* [24..16] */
51  u32 : 1;
52  u32 data_direction : 2; /* [27..26] */
53  u32 : 4;
54  };
55  u32 raw;
57 
58  /* IOSAV_n_SP_CMD_ADDR */
59  union {
60  struct {
61  u32 address : 16; /* [15.. 0] */
62  u32 rowbits : 3; /* [18..16] */
63  u32 : 1;
64  u32 bank : 3; /* [22..20] */
65  u32 : 1;
66  u32 rank : 2; /* [25..24] */
67  u32 : 6;
68  };
69  u32 raw;
71 
72  /* IOSAV_n_ADDR_UPDATE */
73  union {
74  struct {
75  u32 inc_addr_1 : 1; /* [ 0.. 0] */
76  u32 inc_addr_8 : 1; /* [ 1.. 1] */
77  u32 inc_bank : 1; /* [ 2.. 2] */
78  u32 inc_rank : 2; /* [ 4.. 3] */
79  u32 addr_wrap : 5; /* [ 9.. 5] */
80  u32 lfsr_upd : 2; /* [11..10] */
81  u32 upd_rate : 4; /* [15..12] */
82  u32 lfsr_xors : 2; /* [17..16] */
83  u32 : 14;
84  };
85  u32 raw;
87 };
88 
89 union gdcr_rx_reg {
90  struct {
91  u32 rcven_pi_code : 6; /* [ 5.. 0] */
92  u32 : 2;
93  u32 rx_dqs_p_pi_code : 7; /* [14.. 8] */
94  u32 : 1;
95  u32 rcven_logic_delay : 3; /* [18..16] */
96  u32 : 1;
97  u32 rx_dqs_n_pi_code : 7; /* [26..20] */
98  u32 : 5;
99  };
101 };
102 
103 union gdcr_tx_reg {
104  struct {
105  u32 tx_dq_pi_code : 6; /* [ 5.. 0] */
106  u32 : 2;
107  u32 tx_dqs_pi_code : 6; /* [13.. 8] */
108  u32 : 1;
109  u32 tx_dqs_logic_delay : 3; /* [17..15] */
110  u32 : 1;
111  u32 tx_dq_logic_delay : 1; /* [19..19] */
112  u32 : 12;
113  };
115 };
116 
118  struct {
119  u32 cmd_pi_code : 6; /* [ 5.. 0] */
120  u32 ctl_pi_code_d0 : 6; /* [11.. 6] */
121  u32 cmd_logic_delay : 1; /* [12..12] */
122  u32 cmd_phase_delay : 1; /* [13..13] */
123  u32 cmd_xover_enable : 1; /* [14..14] */
124  u32 ctl_logic_delay_d0 : 1; /* [15..15] */
125  u32 ctl_phase_delay_d0 : 1; /* [16..16] */
126  u32 ctl_xover_enable_d0 : 1; /* [17..17] */
127  u32 ctl_pi_code_d1 : 6; /* [23..18] */
128  u32 ctl_logic_delay_d1 : 1; /* [24..24] */
129  u32 ctl_phase_delay_d1 : 1; /* [25..25] */
130  u32 ctl_xover_enable_d1 : 1; /* [26..26] */
131  u32 : 5;
132  };
134 };
135 
137  struct {
138  u32 receive_enable_mode : 1; /* [ 0.. 0] */
139  u32 write_leveling_mode : 1; /* [ 1.. 1] */
140  u32 training_rank_sel : 2; /* [ 3.. 2] */
141  u32 enable_dqs_wl : 4; /* [ 7.. 4] */
142  u32 dqs_logic_delay_wl : 1; /* [ 8.. 8] */
143  u32 dq_dqs_training_res : 1; /* [ 9.. 9] */
144  u32 : 4;
145  u32 delay_dq : 1; /* [14..14] */
146  u32 odt_always_on : 1; /* [15..15] */
147  u32 : 4;
148  u32 force_drive_enable : 1; /* [20..20] */
149  u32 dft_tx_pi_clk_view : 1; /* [21..21] */
150  u32 dft_tx_pi_clk_swap : 1; /* [22..22] */
151  u32 early_odt_en : 1; /* [23..23] */
152  u32 vref_gen_ctl : 6; /* [29..24] */
153  u32 ext_vref_sel : 1; /* [30..30] */
154  u32 tx_fifo_always_on : 1; /* [31..31] */
155  };
157 };
158 
160  struct {
161  u32 dq_odt_down : 3; /* [ 2.. 0] */
162  u32 dq_odt_up : 3; /* [ 5.. 3] */
163  u32 clk_odt_down : 3; /* [ 8.. 6] */
164  u32 clk_odt_up : 3; /* [11.. 9] */
165  u32 dq_drv_down : 3; /* [14..12] */
166  u32 dq_drv_up : 3; /* [17..15] */
167  u32 clk_drv_down : 3; /* [20..18] */
168  u32 clk_drv_up : 3; /* [23..21] */
169  u32 ctl_drv_down : 3; /* [26..24] */
170  u32 ctl_drv_up : 3; /* [29..27] */
171  u32 : 2;
172  };
174 };
175 
176 union tc_dbp_reg {
177  struct {
178  u32 tRCD : 4; /* [ 3.. 0] */
179  u32 tRP : 4; /* [ 7.. 4] */
180  u32 tAA : 4; /* [11.. 8] */
181  u32 tCWL : 4; /* [15..12] */
182  u32 tRAS : 8; /* [23..16] */
183  u32 : 8;
184  };
186 };
187 
188 union tc_rap_reg {
189  struct {
190  u32 tRRD : 4; /* [ 3.. 0] */
191  u32 tRTP : 4; /* [ 7.. 4] */
192  u32 tCKE : 4; /* [11.. 8] */
193  u32 tWTR : 4; /* [15..12] */
194  u32 tFAW : 8; /* [23..16] */
195  u32 tWR : 5; /* [28..24] */
196  u32 dis_3st : 1; /* [29..29] */
197  u32 tCMD : 2; /* [31..30] */
198  };
200 };
201 
202 union tc_rwp_reg {
203  struct {
204  u32 tRRDR : 3; /* [ 2.. 0] */
205  u32 : 1;
206  u32 tRRDD : 3; /* [ 6.. 4] */
207  u32 : 1;
208  u32 tWWDR : 3; /* [10.. 8] */
209  u32 : 1;
210  u32 tWWDD : 3; /* [14..12] */
211  u32 : 1;
212  u32 tRWDRDD : 3; /* [18..16] */
213  u32 : 1;
214  u32 tWRDRDD : 3; /* [22..20] */
215  u32 : 1;
216  u32 tRWSR : 3; /* [26..24] */
217  u32 dec_wrd : 1; /* [27..27] */
218  u32 : 4;
219  };
221 };
222 
223 union tc_othp_reg {
224  struct {
225  u32 tXPDLL : 5; /* [ 4.. 0] */
226  u32 tXP : 3; /* [ 7.. 5] */
227  u32 tAONPD : 4; /* [11.. 8] */
228  u32 tCPDED : 2; /* [13..12] */
229  u32 tPRPDEN : 2; /* [15..14] */
230  u32 odt_delay_d0 : 2; /* [17..16] */
231  u32 odt_delay_d1 : 2; /* [19..18] */
232  u32 : 12;
233  };
235 };
236 
237 union tc_dtp_reg {
238  struct {
239  u32 : 12;
240  u32 overclock_tXP : 1; /* [12..12] */
241  u32 overclock_tXPDLL : 1; /* [13..13] */
242  u32 : 18;
243  };
245 };
246 
247 union tc_rfp_reg {
248  struct {
249  u32 oref_ri : 8; /* [ 7.. 0] */
250  u32 refresh_high_wm : 4; /* [11.. 8] */
251  u32 refresh_panic_wm : 4; /* [15..12] */
252  u32 refresh_2x_control : 2; /* [17..16] */
253  u32 : 14;
254  };
256 };
257 
258 union tc_rftp_reg {
259  struct {
260  u32 tREFI : 16; /* [15.. 0] */
261  u32 tRFC : 9; /* [24..16] */
262  u32 tREFIx9 : 7; /* [31..25] */
263  };
265 };
266 
268  struct {
269  u32 tXSDLL : 12; /* [11.. 0] */
270  u32 tXS_offset : 4; /* [15..12] */
271  u32 tZQOPER : 10; /* [25..16] */
272  u32 : 2;
273  u32 tMOD : 4; /* [31..28] */
274  };
276 };
277 
278 typedef struct ramctr_timing_st ramctr_timing;
279 
280 void iosav_write_sequence(const int ch, const struct iosav_ssq *seq, const unsigned int length);
281 void iosav_run_queue(const int ch, const u8 loops, const u8 as_timer);
282 void wait_for_iosav(int channel);
283 void iosav_run_once_and_wait(const int ch);
284 
285 void iosav_write_zqcs_sequence(int channel, int slotrank, u32 gap, u32 post, u32 wrap);
286 void iosav_write_prea_sequence(int channel, int slotrank, u32 post, u32 wrap);
288  int channel, int slotrank, u32 tMOD, u32 loops, u32 gap, u32 loops2, u32 post2);
289 void iosav_write_prea_act_read_sequence(ramctr_timing *ctrl, int channel, int slotrank);
291  ramctr_timing *ctrl, int channel, int slotrank, int bank, u32 mr1reg);
292 void iosav_write_misc_write_sequence(ramctr_timing *ctrl, int channel, int slotrank,
293  u32 gap0, u32 loops0, u32 gap1, u32 loops2, u32 wrap2);
295  ramctr_timing *ctrl, int channel, int slotrank, unsigned int address);
296 void iosav_write_data_write_sequence(ramctr_timing *ctrl, int channel, int slotrank);
297 void iosav_write_aggressive_write_read_sequence(ramctr_timing *ctrl, int channel, int slotrank);
298 void iosav_write_memory_test_sequence(ramctr_timing *ctrl, int channel, int slotrank);
299 
300 /* FIXME: Vendor BIOS uses 64 but our algorithms are less
301  performant and even 1 seems to be enough in practice. */
302 #define NUM_PATTERNS 4
303 
304 /*
305  * WARNING: Do not forget to increase MRC_CACHE_VERSION when the saved data is changed!
306  */
307 #define MRC_CACHE_VERSION 5
308 
310  PDM_NONE = 0,
311  PDM_APD = 1,
312  PDM_PPD = 2,
316 };
317 
318 typedef struct odtmap_st {
322 
323 /* WARNING: Do not forget to increase MRC_CACHE_VERSION when this struct is changed! */
324 typedef struct dimm_info_st {
327 
328 /* WARNING: Do not forget to increase MRC_CACHE_VERSION when this struct is changed! */
330  /* ROUNDT_LAT register: One byte per slotrank */
332 
333  /* IO_LATENCY register: One nibble per slotrank */
335 
336  /* Phase interpolator coding for command and control */
338 
340  /* GDCR RX timings */
344 
345  /* GDCR TX timings */
346  int tx_dq;
349 };
350 
351 /* WARNING: Do not forget to increase MRC_CACHE_VERSION when this struct is changed! */
352 typedef struct ramctr_timing_st {
354 
355  /* CPUID value */
357 
358  /* DDR base_freq = 100 Mhz / 133 Mhz */
360 
361  /* Frequency index */
363 
365  /* Latencies are in units of ns, scaled by x256 */
379  /* Latencies in terms of clock cycles
380  They are saved separately as they are needed for DRAM MRS commands */
381  u8 CAS; /* CAS read latency */
382  u8 CWL; /* CAS write latency */
383 
392 
393  /* Bits [0..11] of PM_DLL_CONFIG: Master DLL wakeup delay timer */
395 
401 
404 
408  int lanes; /* active lanes: 8 or 9 */
409  int edge_offset[3];
410  int tx_dq_offset[3];
411 
414 
416 
418 
420 } ramctr_timing;
421 
422 #define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0)
423 
424 #define FOR_ALL_LANES for (lane = 0; lane < ctrl->lanes; lane++)
425 #define FOR_ALL_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++)
426 #define FOR_ALL_POPULATED_RANKS for (slotrank = 0; slotrank < NUM_SLOTRANKS; slotrank++) if (ctrl->rankmap[channel] & (1 << slotrank))
427 #define FOR_ALL_POPULATED_CHANNELS for (channel = 0; channel < NUM_CHANNELS; channel++) if (ctrl->rankmap[channel])
428 #define MAX_EDGE_TIMING 71
429 #define MAX_TX_DQ 127
430 #define MAX_TX_DQS 511
431 #define MAX_RCVEN 127
432 #define MAX_CAS 18
433 #define MIN_CAS 4
434 
435 /*
436  * 1 QCLK (quadrature clock) is one half of a full clock cycle (tCK).
437  * In addition, 64 PI (phase interpolator) ticks are equal to 1 QCLK.
438  * Logic delay values in I/O register bitfields are expressed in QCLKs.
439  */
440 #define QCLK_PI 64
441 
442 #define MAKE_ERR ((channel << 16) | (slotrank << 8) | 1)
443 #define GET_ERR_CHANNEL(x) (x >> 16)
444 
445 void dram_mrscommands(ramctr_timing *ctrl);
446 void program_timings(ramctr_timing *ctrl, int channel);
448 void dram_xover(ramctr_timing *ctrl);
449 void dram_timing_regs(ramctr_timing *ctrl);
450 void dram_dimm_mapping(ramctr_timing *ctrl);
451 void dram_dimm_set_mapping(ramctr_timing *ctrl, int training);
452 void dram_zones(ramctr_timing *ctrl, int training);
453 void dram_memorymap(ramctr_timing *ctrl, int me_uma_size);
454 void dram_jedecreset(ramctr_timing *ctrl);
456 int write_training(ramctr_timing *ctrl);
462 int channel_test(ramctr_timing *ctrl);
464 void set_wmm_behavior(const u32 cpu);
465 void prepare_training(ramctr_timing *ctrl);
468 void final_registers(ramctr_timing *ctrl);
469 void restore_timings(ramctr_timing *ctrl);
470 int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot, int s3resume, int me_uma_size);
471 
472 void channel_scrub(ramctr_timing *ctrl);
473 bool get_host_ecc_cap(void);
474 bool get_host_ecc_forced(void);
475 
476 #endif
uint64_t length
Definition: fw_cfg_if.h:1
uint64_t address
Definition: fw_cfg_if.h:0
static struct dramc_channel const ch[2]
int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot, int s3resume, int me_uma_size)
void iosav_write_prea_sequence(int channel, int slotrank, u32 post, u32 wrap)
Definition: raminit_iosav.c:79
void normalize_training(ramctr_timing *ctrl)
void iosav_run_queue(const int ch, const u8 loops, const u8 as_timer)
Definition: raminit_iosav.c:28
void dram_memorymap(ramctr_timing *ctrl, int me_uma_size)
void iosav_write_aggressive_write_read_sequence(ramctr_timing *ctrl, int channel, int slotrank)
int command_training(ramctr_timing *ctrl)
void iosav_write_command_training_sequence(ramctr_timing *ctrl, int channel, int slotrank, unsigned int address)
bool get_host_ecc_cap(void)
int aggressive_write_training(ramctr_timing *ctrl)
int aggressive_read_training(ramctr_timing *ctrl)
power_down_mode
@ PDM_NONE
@ PDM_PPD
@ PDM_DLL_OFF
@ PDM_APD_DLL_OFF
@ PDM_APD_PPD
@ PDM_APD
void dram_dimm_set_mapping(ramctr_timing *ctrl, int training)
void iosav_write_memory_test_sequence(ramctr_timing *ctrl, int channel, int slotrank)
struct dimm_info_st dimm_info
void set_read_write_timings(ramctr_timing *ctrl)
#define NUM_SLOTRANKS
void dram_mrscommands(ramctr_timing *ctrl)
struct ramctr_timing_st ramctr_timing
void iosav_write_read_mpr_sequence(int channel, int slotrank, u32 tMOD, u32 loops, u32 gap, u32 loops2, u32 post2)
void set_normal_operation(ramctr_timing *ctrl)
void restore_timings(ramctr_timing *ctrl)
void iosav_write_zqcs_sequence(int channel, int slotrank, u32 gap, u32 post, u32 wrap)
Definition: raminit_iosav.c:51
void dram_find_common_params(ramctr_timing *ctrl)
void program_timings(ramctr_timing *ctrl, int channel)
void prepare_training(ramctr_timing *ctrl)
#define NUM_LANES
void final_registers(ramctr_timing *ctrl)
void iosav_write_misc_write_sequence(ramctr_timing *ctrl, int channel, int slotrank, u32 gap0, u32 loops0, u32 gap1, u32 loops2, u32 wrap2)
#define NUM_SLOTS
void iosav_run_once_and_wait(const int ch)
Definition: raminit_iosav.c:45
void channel_scrub(ramctr_timing *ctrl)
struct odtmap_st odtmap
void dram_xover(ramctr_timing *ctrl)
void iosav_write_prea_act_read_sequence(ramctr_timing *ctrl, int channel, int slotrank)
int read_mpr_training(ramctr_timing *ctrl)
void wait_for_iosav(int channel)
Definition: raminit_iosav.c:37
void iosav_write_sequence(const int ch, const struct iosav_ssq *seq, const unsigned int length)
Definition: raminit_iosav.c:16
bool get_host_ecc_forced(void)
void dram_dimm_mapping(ramctr_timing *ctrl)
void dram_zones(ramctr_timing *ctrl, int training)
int channel_test(ramctr_timing *ctrl)
void iosav_write_data_write_sequence(ramctr_timing *ctrl, int channel, int slotrank)
void dram_jedecreset(ramctr_timing *ctrl)
void set_wmm_behavior(const u32 cpu)
void iosav_write_jedec_write_leveling_sequence(ramctr_timing *ctrl, int channel, int slotrank, int bank, u32 mr1reg)
void dram_timing_regs(ramctr_timing *ctrl)
#define NUM_CHANNELS
int receive_enable_calibration(ramctr_timing *ctrl)
int write_training(ramctr_timing *ctrl)
void set_scrambling_seed(ramctr_timing *ctrl)
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
DIMM characteristics.
Definition: ddr3.h:106
struct dimm_attr_ddr3_st dimm[NUM_CHANNELS][NUM_SLOTS]
If this table is filled and put in CBMEM, then these info in CBMEM will be used to generate smbios ty...
Definition: memory_info.h:19
u32 data_direction
u32 cmd_delay_gap
union iosav_ssq::@335 subseq_ctrl
union iosav_ssq::@337 addr_update
u32 cmd_executions
union iosav_ssq::@334 sp_cmd_ctrl
u32 post_ssq_wait
union iosav_ssq::@336 sp_cmd_addr
struct ram_rank_timings::ram_lane_timings lanes[NUM_LANES]
u8 rankmap[NUM_CHANNELS]
int rank_mirror[NUM_CHANNELS][NUM_SLOTRANKS]
u32 cmd_stretch[NUM_CHANNELS]
u16 spd_crc[NUM_CHANNELS][NUM_SLOTS]
int ref_card_offset[NUM_CHANNELS]
int channel_size_mb[NUM_CHANNELS]
u32 mad_dimm[NUM_CHANNELS]
u32 rcven_logic_delay
u32 rx_dqs_p_pi_code
u32 rx_dqs_n_pi_code
u32 tx_dqs_logic_delay
u32 overclock_tXPDLL
u32 refresh_2x_control
u32 refresh_panic_wm