blob: 2ded8a8fdbae2b698a4e1490a5553224cdd1a4b4 [file] [log] [blame]
Patrick Georgi02363b52020-05-05 20:48:50 +02001/* This file is part of the coreboot project. */
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -05002/*
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -05003 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
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.
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050013 */
14
Elyes HAOUASaa8e7e72016-06-19 12:38:47 +020015/*
16 * JEDEC Standard No. 21-C
17 * Annex K: Serial Presence Detect (SPD) for DDR3 SDRAM Modules 2014
18 * http://www.jedec.org/sites/default/files/docs/4_01_02_11R24.pdf
19 */
20
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050021#ifndef DEVICE_DRAM_DDR3L_H
22#define DEVICE_DRAM_DDR3L_H
23
24/**
25 * @file ddr3.h
26 *
27 * \brief Utilities for decoding DDR3 SPDs
28 */
29
30#include <stdint.h>
31#include <spd.h>
Arthur Heymansfc31e442018-02-12 15:12:34 +010032#include <device/dram/common.h>
Patrick Rudolph24efe732018-08-19 11:06:06 +020033#include <types.h>
Arthur Heymansfc31e442018-02-12 15:12:34 +010034
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050035
36/**
Matt DeVillier5aaa8ce2016-09-02 13:29:17 -050037 * Convenience definitions for SPD offsets
38 *
39 * @{
40 */
41#define SPD_DIMM_MOD_ID1 117
42#define SPD_DIMM_MOD_ID2 118
43#define SPD_DIMM_SERIAL_NUM 122
44#define SPD_DIMM_SERIAL_LEN 4
45#define SPD_DIMM_PART_NUM 128
46#define SPD_DIMM_PART_LEN 18
47/** @} */
48
49/**
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050050 * \brief Convenience macro for enabling printk with CONFIG_DEBUG_RAM_SETUP
51 *
52 * Use this macro instead of printk(); for verbose RAM initialization messages.
53 * When CONFIG_DEBUG_RAM_SETUP is not selected, these messages are automatically
54 * disabled.
55 * @{
56 */
Julius Wernercd49cce2019-03-05 16:53:33 -080057#if CONFIG(DEBUG_RAM_SETUP)
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050058#define printram(x, ...) printk(BIOS_DEBUG, x, ##__VA_ARGS__)
59#else
60#define printram(x, ...)
61#endif
62/** @} */
63
64/*
65 * Module type (byte 3, bits 3:0) of SPD
Martin Roth0cb07e32013-07-09 21:46:01 -060066 * This definition is specific to DDR3. DDR2 SPDs have a different structure.
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050067 */
68enum spd_dimm_type {
69 SPD_DIMM_TYPE_UNDEFINED = 0x00,
70 SPD_DIMM_TYPE_RDIMM = 0x01,
71 SPD_DIMM_TYPE_UDIMM = 0x02,
72 SPD_DIMM_TYPE_SO_DIMM = 0x03,
73 SPD_DIMM_TYPE_MICRO_DIMM = 0x04,
74 SPD_DIMM_TYPE_MINI_RDIMM = 0x05,
75 SPD_DIMM_TYPE_MINI_UDIMM = 0x06,
76 SPD_DIMM_TYPE_MINI_CDIMM = 0x07,
77 SPD_DIMM_TYPE_72B_SO_UDIMM = 0x08,
78 SPD_DIMM_TYPE_72B_SO_RDIMM = 0x09,
79 SPD_DIMM_TYPE_72B_SO_CDIMM = 0x0a,
80 SPD_DIMM_TYPE_LRDIMM = 0x0b,
Elyes HAOUASaa8e7e72016-06-19 12:38:47 +020081 SPD_DIMM_TYPE_16B_SO_DIMM = 0x0c,
82 SPD_DIMM_TYPE_32B_SO_DIMM = 0x0d,
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050083 /* Masks to bits 3:0 to give the dimm type */
84 SPD_DIMM_TYPE_MASK = 0x0f,
85};
86
87/**
88 * \brief DIMM flags
89 *
90 * Characteristic flags for the DIMM, as presented by the SPD
91 */
92typedef union dimm_flags_st {
93 /* The whole point of the union/struct construct is to allow us to clear
94 * all the bits with one line: flags.raw = 0.
95 * We do not care how these bits are ordered */
96 struct {
97 /* Indicates if rank 1 of DIMM uses a mirrored pin mapping. See:
98 * Annex K: Serial Presence Detect (SPD) for DDR3 SDRAM */
Lee Leahy0ca2a062017-03-06 18:01:04 -080099 unsigned int pins_mirrored:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500100 /* Module can work at 1.50V - All DIMMS must be 1.5V operable */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800101 unsigned int operable_1_50V:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500102 /* Module can work at 1.35V */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800103 unsigned int operable_1_35V:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500104 /* Module can work at 1.20V */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800105 unsigned int operable_1_25V:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500106 /* Has an 8-bit bus extension, meaning the DIMM supports ECC */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800107 unsigned int is_ecc:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500108 /* DLL-Off Mode Support */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800109 unsigned int dll_off_mode:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500110 /* Indicates a drive strength of RZQ/6 (40 Ohm) is supported */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800111 unsigned int rzq6_supported:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500112 /* Indicates a drive strength of RZQ/7 (35 Ohm) is supported */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800113 unsigned int rzq7_supported:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500114 /* Partial Array Self Refresh */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800115 unsigned int pasr:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500116 /* On-die Thermal Sensor Readout */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800117 unsigned int odts:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500118 /* Auto Self Refresh */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800119 unsigned int asr:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500120 /* Extended temperature range supported */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800121 unsigned int ext_temp_range:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500122 /* Operating at extended temperature requires 2X refresh rate */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800123 unsigned int ext_temp_refresh:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500124 /* Thermal sensor incorporated */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800125 unsigned int therm_sensor:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500126 };
Lee Leahy0ca2a062017-03-06 18:01:04 -0800127 unsigned int raw;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500128} dimm_flags_t;
129
130/**
131 * \brief DIMM characteristics
132 *
133 * The characteristics of each DIMM, as presented by the SPD
134 */
135typedef struct dimm_attr_st {
136 enum spd_memory_type dram_type;
Vladimir Serbinenko0e675f72014-12-07 13:56:48 +0100137 enum spd_dimm_type dimm_type;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500138 u16 cas_supported;
139 /* Flags extracted from SPD */
140 dimm_flags_t flags;
Vladimir Serbinenko7686a562014-05-18 11:05:56 +0200141 /* SDRAM width */
142 u8 width;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500143 /* Number of ranks */
144 u8 ranks;
145 /* Number or row address bits */
146 u8 row_bits;
147 /* Number or column address bits */
148 u8 col_bits;
149 /* Size of module in MiB */
150 u32 size_mb;
151 /* Latencies are in units of 1/256 ns */
152 u32 tCK;
153 u32 tAA;
154 u32 tWR;
155 u32 tRCD;
156 u32 tRRD;
157 u32 tRP;
158 u32 tRAS;
159 u32 tRC;
160 u32 tRFC;
161 u32 tWTR;
162 u32 tRTP;
163 u32 tFAW;
Dan Elkouby0c024202018-04-13 18:45:02 +0300164 u32 tCWL;
165 u16 tCMD;
Vladimir Serbinenko7686a562014-05-18 11:05:56 +0200166
167 u8 reference_card;
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100168 /* XMP: Module voltage in mV */
169 u16 voltage;
170 /* XMP: max DIMMs per channel supported (1-4) */
171 u8 dimms_per_channel;
Patrick Rudolph07691592016-02-29 18:21:00 +0100172 /* Manufacturer ID */
173 u16 manufacturer_id;
174 /* ASCII part number - NULL terminated */
175 u8 part_number[17];
Patrick Rudolph15e64692018-08-17 15:24:56 +0200176 /* Serial number */
177 u8 serial[SPD_DIMM_SERIAL_LEN];
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500178} dimm_attr;
179
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100180enum ddr3_xmp_profile {
181 DDR3_XMP_PROFILE_1 = 0,
182 DDR3_XMP_PROFILE_2 = 1,
183};
184
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500185typedef u8 spd_raw_data[256];
186
Alexandru Gagniuc4c37e582013-12-17 13:08:01 -0500187u16 spd_ddr3_calc_crc(u8 *spd, int len);
Kyösti Mälkki7dc4b842016-11-18 18:41:17 +0200188u16 spd_ddr3_calc_unique_crc(u8 *spd, int len);
Lee Leahy6d71a432017-03-07 15:24:16 -0800189int spd_decode_ddr3(dimm_attr *dimm, spd_raw_data spd_data);
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100190int spd_dimm_is_registered_ddr3(enum spd_dimm_type type);
Lee Leahy6d71a432017-03-07 15:24:16 -0800191void dram_print_spd_ddr3(const dimm_attr *dimm);
192int spd_xmp_decode_ddr3(dimm_attr *dimm,
Lee Leahy708fc272017-03-07 12:18:53 -0800193 spd_raw_data spd,
194 enum ddr3_xmp_profile profile);
Patrick Rudolph24efe732018-08-19 11:06:06 +0200195enum cb_err spd_add_smbios17(const u8 channel, const u8 slot,
196 const u16 selected_freq,
197 const dimm_attr *info);
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500198/**
199 * \brief Read double word from specified address
200 *
201 * Should be useful when doing an MRS to the DIMM
202 */
Stefan Reinauer1e2500e2015-06-19 14:59:06 -0700203static inline u32 volatile_read(volatile uintptr_t addr)
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500204{
205 volatile u32 result;
206 result = *(volatile u32 *)addr;
207 return result;
208}
209
Alexandru Gagniuc78706fd2013-06-03 13:58:10 -0500210/**
211 * \brief Representation of an MRS command
212 *
213 * This represents an MRS command as seen by the DIMM. This is not a memory
214 * address that can be read to generate an MRS command. The mapping of CPU
215 * to memory pins is hardware-dependent.
216 * \n
217 * The idea is to generalize the MRS code, and only need a hardware-specific
218 * function to map the MRS bits to CPU address bits. An MRS command can be
219 * sent like:
220 * @code{.c}
221 * u32 addr;
222 * mrs_cmd_t mrs;
223 * chipset_enable_mrs_command_mode();
224 * mrs = ddr3_get_mr2(rtt_wr, srt, asr, cwl)
225 * if (rank_has_mirrorred_pins)
226 * mrs = ddr3_mrs_mirror_pins(mrs);
227 * addr = chipset_specific_get_mrs_addr(mrs);
228 * volatile_read(addr);
229 * @endcode
230 *
231 * The MRS representation has the following structure:
232 * - cmd[15:0] = Address pins MA[15:0]
233 * - cmd[18:16] = Bank address BA[2:0]
234 */
235typedef u32 mrs_cmd_t;
236
237enum ddr3_mr0_precharge {
238 DDR3_MR0_PRECHARGE_SLOW = 0,
239 DDR3_MR0_PRECHARGE_FAST = 1,
240};
241enum ddr3_mr0_mode {
242 DDR3_MR0_MODE_NORMAL = 0,
243 DDR3_MR0_MODE_TEST = 1,
244};
245enum ddr3_mr0_dll_reset {
246 DDR3_MR0_DLL_RESET_NO = 0,
247 DDR3_MR0_DLL_RESET_YES = 1,
248};
249enum ddr3_mr0_burst_type {
250 DDR3_MR0_BURST_TYPE_SEQUENTIAL = 0,
251 DDR3_MR0_BURST_TYPE_INTERLEAVED = 1,
252};
253enum ddr3_mr0_burst_length {
254 DDR3_MR0_BURST_LENGTH_8 = 0,
255 DDR3_MR0_BURST_LENGTH_CHOP = 1,
256 DDR3_MR0_BURST_LENGTH_4 = 2,
257};
258mrs_cmd_t ddr3_get_mr0(enum ddr3_mr0_precharge precharge_pd,
259 u8 write_recovery,
260 enum ddr3_mr0_dll_reset dll_reset,
261 enum ddr3_mr0_mode mode,
262 u8 cas,
263 enum ddr3_mr0_burst_type interleaved_burst,
264 enum ddr3_mr0_burst_length burst_length);
265
266enum ddr3_mr1_qoff {
267 DDR3_MR1_QOFF_ENABLE = 0,
268 DDR3_MR1_QOFF_DISABLE = 1,
269};
270enum ddr3_mr1_tqds {
271 DDR3_MR1_TQDS_DISABLE = 0,
272 DDR3_MR1_TQDS_ENABLE = 1,
273};
274enum ddr3_mr1_write_leveling {
275 DDR3_MR1_WRLVL_DISABLE = 0,
276 DDR3_MR1_WRLVL_ENABLE = 1,
277};
278enum ddr3_mr1_rtt_nom {
279 DDR3_MR1_RTT_NOM_OFF = 0,
280 DDR3_MR1_RTT_NOM_RZQ4 = 1,
281 DDR3_MR1_RTT_NOM_RZQ2 = 2,
282 DDR3_MR1_RTT_NOM_RZQ6 = 3,
283 DDR3_MR1_RTT_NOM_RZQ12 = 4,
284 DDR3_MR1_RTT_NOM_RZQ8 = 5,
285};
286enum ddr3_mr1_additive_latency {
287 DDR3_MR1_AL_DISABLE = 0,
288 DDR3_MR1_AL_CL_MINUS_1 = 1,
289 DDR3_MR1_AL_CL_MINUS_2 = 2,
290};
291enum ddr3_mr1_ods {
292 DDR3_MR1_ODS_RZQ6 = 0,
293 DDR3_MR1_ODS_RZQ7 = 1,
294};
295enum ddr3_mr1_dll {
296 DDR3_MR1_DLL_ENABLE = 0,
297 DDR3_MR1_DLL_DISABLE = 1,
298};
299
300mrs_cmd_t ddr3_get_mr1(enum ddr3_mr1_qoff qoff,
301 enum ddr3_mr1_tqds tqds,
302 enum ddr3_mr1_rtt_nom rtt_nom,
303 enum ddr3_mr1_write_leveling write_leveling,
304 enum ddr3_mr1_ods output_drive_strenght,
305 enum ddr3_mr1_additive_latency additive_latency,
306 enum ddr3_mr1_dll dll_disable);
307
308enum ddr3_mr2_rttwr {
309 DDR3_MR2_RTTWR_OFF = 0,
310 DDR3_MR2_RTTWR_RZQ4 = 1,
311 DDR3_MR2_RTTWR_RZQ2 = 2,
312};
313enum ddr3_mr2_srt_range {
314 DDR3_MR2_SRT_NORMAL = 0,
315 DDR3_MR2_SRT_EXTENDED = 1,
316};
317enum ddr3_mr2_asr {
318 DDR3_MR2_ASR_MANUAL = 0,
319 DDR3_MR2_ASR_AUTO = 1,
320};
321
322mrs_cmd_t ddr3_get_mr2(enum ddr3_mr2_rttwr rtt_wr,
323 enum ddr3_mr2_srt_range extended_temp,
324 enum ddr3_mr2_asr self_refresh, u8 cas_cwl);
325
326mrs_cmd_t ddr3_get_mr3(char dataflow_from_mpr);
327mrs_cmd_t ddr3_mrs_mirror_pins(mrs_cmd_t cmd);
328
Martin Rothfd277d82016-01-11 12:47:30 -0700329#endif /* DEVICE_DRAM_DDR3L_H */