blob: 74e0ff55f1a7ea14f7bdafbecb764af5a82715fc [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -05002
Elyes HAOUASaa8e7e72016-06-19 12:38:47 +02003/*
4 * JEDEC Standard No. 21-C
5 * Annex K: Serial Presence Detect (SPD) for DDR3 SDRAM Modules 2014
6 * http://www.jedec.org/sites/default/files/docs/4_01_02_11R24.pdf
7 */
8
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -05009#ifndef DEVICE_DRAM_DDR3L_H
10#define DEVICE_DRAM_DDR3L_H
11
12/**
13 * @file ddr3.h
14 *
15 * \brief Utilities for decoding DDR3 SPDs
16 */
17
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050018#include <spd.h>
Arthur Heymansfc31e442018-02-12 15:12:34 +010019#include <device/dram/common.h>
Patrick Rudolph24efe732018-08-19 11:06:06 +020020#include <types.h>
Arthur Heymansfc31e442018-02-12 15:12:34 +010021
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050022
23/**
Matt DeVillier5aaa8ce2016-09-02 13:29:17 -050024 * Convenience definitions for SPD offsets
25 *
26 * @{
27 */
28#define SPD_DIMM_MOD_ID1 117
29#define SPD_DIMM_MOD_ID2 118
30#define SPD_DIMM_SERIAL_NUM 122
31#define SPD_DIMM_SERIAL_LEN 4
32#define SPD_DIMM_PART_NUM 128
33#define SPD_DIMM_PART_LEN 18
34/** @} */
35
36/**
Martin Rothf48acbd2020-07-24 12:24:27 -060037 * \brief Convenience macro for enabling printk with CONFIG(DEBUG_RAM_SETUP)
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050038 *
39 * Use this macro instead of printk(); for verbose RAM initialization messages.
Martin Rothf48acbd2020-07-24 12:24:27 -060040 * When CONFIG(DEBUG_RAM_SETUP) is not selected, these messages are automatically
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050041 * disabled.
42 * @{
43 */
Julius Wernercd49cce2019-03-05 16:53:33 -080044#if CONFIG(DEBUG_RAM_SETUP)
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050045#define printram(x, ...) printk(BIOS_DEBUG, x, ##__VA_ARGS__)
46#else
47#define printram(x, ...)
48#endif
49/** @} */
50
51/*
52 * Module type (byte 3, bits 3:0) of SPD
Martin Roth0cb07e32013-07-09 21:46:01 -060053 * This definition is specific to DDR3. DDR2 SPDs have a different structure.
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050054 */
55enum spd_dimm_type {
56 SPD_DIMM_TYPE_UNDEFINED = 0x00,
57 SPD_DIMM_TYPE_RDIMM = 0x01,
58 SPD_DIMM_TYPE_UDIMM = 0x02,
59 SPD_DIMM_TYPE_SO_DIMM = 0x03,
60 SPD_DIMM_TYPE_MICRO_DIMM = 0x04,
61 SPD_DIMM_TYPE_MINI_RDIMM = 0x05,
62 SPD_DIMM_TYPE_MINI_UDIMM = 0x06,
63 SPD_DIMM_TYPE_MINI_CDIMM = 0x07,
64 SPD_DIMM_TYPE_72B_SO_UDIMM = 0x08,
65 SPD_DIMM_TYPE_72B_SO_RDIMM = 0x09,
66 SPD_DIMM_TYPE_72B_SO_CDIMM = 0x0a,
67 SPD_DIMM_TYPE_LRDIMM = 0x0b,
Elyes HAOUASaa8e7e72016-06-19 12:38:47 +020068 SPD_DIMM_TYPE_16B_SO_DIMM = 0x0c,
69 SPD_DIMM_TYPE_32B_SO_DIMM = 0x0d,
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050070 /* Masks to bits 3:0 to give the dimm type */
71 SPD_DIMM_TYPE_MASK = 0x0f,
72};
73
74/**
75 * \brief DIMM flags
76 *
77 * Characteristic flags for the DIMM, as presented by the SPD
78 */
79typedef union dimm_flags_st {
80 /* The whole point of the union/struct construct is to allow us to clear
81 * all the bits with one line: flags.raw = 0.
82 * We do not care how these bits are ordered */
83 struct {
84 /* Indicates if rank 1 of DIMM uses a mirrored pin mapping. See:
85 * Annex K: Serial Presence Detect (SPD) for DDR3 SDRAM */
Lee Leahy0ca2a062017-03-06 18:01:04 -080086 unsigned int pins_mirrored:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050087 /* Module can work at 1.50V - All DIMMS must be 1.5V operable */
Lee Leahy0ca2a062017-03-06 18:01:04 -080088 unsigned int operable_1_50V:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050089 /* Module can work at 1.35V */
Lee Leahy0ca2a062017-03-06 18:01:04 -080090 unsigned int operable_1_35V:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050091 /* Module can work at 1.20V */
Lee Leahy0ca2a062017-03-06 18:01:04 -080092 unsigned int operable_1_25V:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050093 /* Has an 8-bit bus extension, meaning the DIMM supports ECC */
Lee Leahy0ca2a062017-03-06 18:01:04 -080094 unsigned int is_ecc:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050095 /* DLL-Off Mode Support */
Lee Leahy0ca2a062017-03-06 18:01:04 -080096 unsigned int dll_off_mode:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050097 /* Indicates a drive strength of RZQ/6 (40 Ohm) is supported */
Lee Leahy0ca2a062017-03-06 18:01:04 -080098 unsigned int rzq6_supported:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -050099 /* Indicates a drive strength of RZQ/7 (35 Ohm) is supported */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800100 unsigned int rzq7_supported:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500101 /* Partial Array Self Refresh */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800102 unsigned int pasr:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500103 /* On-die Thermal Sensor Readout */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800104 unsigned int odts:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500105 /* Auto Self Refresh */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800106 unsigned int asr:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500107 /* Extended temperature range supported */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800108 unsigned int ext_temp_range:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500109 /* Operating at extended temperature requires 2X refresh rate */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800110 unsigned int ext_temp_refresh:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500111 /* Thermal sensor incorporated */
Lee Leahy0ca2a062017-03-06 18:01:04 -0800112 unsigned int therm_sensor:1;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500113 };
Lee Leahy0ca2a062017-03-06 18:01:04 -0800114 unsigned int raw;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500115} dimm_flags_t;
116
117/**
118 * \brief DIMM characteristics
119 *
120 * The characteristics of each DIMM, as presented by the SPD
121 */
122typedef struct dimm_attr_st {
123 enum spd_memory_type dram_type;
Vladimir Serbinenko0e675f72014-12-07 13:56:48 +0100124 enum spd_dimm_type dimm_type;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500125 u16 cas_supported;
126 /* Flags extracted from SPD */
127 dimm_flags_t flags;
Vladimir Serbinenko7686a562014-05-18 11:05:56 +0200128 /* SDRAM width */
129 u8 width;
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500130 /* Number of ranks */
131 u8 ranks;
132 /* Number or row address bits */
133 u8 row_bits;
134 /* Number or column address bits */
135 u8 col_bits;
136 /* Size of module in MiB */
137 u32 size_mb;
138 /* Latencies are in units of 1/256 ns */
139 u32 tCK;
140 u32 tAA;
141 u32 tWR;
142 u32 tRCD;
143 u32 tRRD;
144 u32 tRP;
145 u32 tRAS;
146 u32 tRC;
147 u32 tRFC;
148 u32 tWTR;
149 u32 tRTP;
150 u32 tFAW;
Dan Elkouby0c024202018-04-13 18:45:02 +0300151 u32 tCWL;
152 u16 tCMD;
Vladimir Serbinenko7686a562014-05-18 11:05:56 +0200153
154 u8 reference_card;
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100155 /* XMP: Module voltage in mV */
156 u16 voltage;
157 /* XMP: max DIMMs per channel supported (1-4) */
158 u8 dimms_per_channel;
Patrick Rudolph07691592016-02-29 18:21:00 +0100159 /* Manufacturer ID */
160 u16 manufacturer_id;
161 /* ASCII part number - NULL terminated */
162 u8 part_number[17];
Patrick Rudolph15e64692018-08-17 15:24:56 +0200163 /* Serial number */
164 u8 serial[SPD_DIMM_SERIAL_LEN];
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500165} dimm_attr;
166
Patrick Rudolphbd1fdc62016-01-26 08:45:21 +0100167enum ddr3_xmp_profile {
168 DDR3_XMP_PROFILE_1 = 0,
169 DDR3_XMP_PROFILE_2 = 1,
170};
171
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500172typedef u8 spd_raw_data[256];
173
Alexandru Gagniuc4c37e582013-12-17 13:08:01 -0500174u16 spd_ddr3_calc_crc(u8 *spd, int len);
Kyösti Mälkki7dc4b842016-11-18 18:41:17 +0200175u16 spd_ddr3_calc_unique_crc(u8 *spd, int len);
Lee Leahy6d71a432017-03-07 15:24:16 -0800176int spd_decode_ddr3(dimm_attr *dimm, spd_raw_data spd_data);
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100177int spd_dimm_is_registered_ddr3(enum spd_dimm_type type);
Lee Leahy6d71a432017-03-07 15:24:16 -0800178void dram_print_spd_ddr3(const dimm_attr *dimm);
179int spd_xmp_decode_ddr3(dimm_attr *dimm,
Lee Leahy708fc272017-03-07 12:18:53 -0800180 spd_raw_data spd,
181 enum ddr3_xmp_profile profile);
Patrick Rudolph24efe732018-08-19 11:06:06 +0200182enum cb_err spd_add_smbios17(const u8 channel, const u8 slot,
183 const u16 selected_freq,
184 const dimm_attr *info);
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500185/**
186 * \brief Read double word from specified address
187 *
188 * Should be useful when doing an MRS to the DIMM
189 */
Stefan Reinauer1e2500e2015-06-19 14:59:06 -0700190static inline u32 volatile_read(volatile uintptr_t addr)
Alexandru Gagniucf97ff3f2013-05-21 14:43:45 -0500191{
192 volatile u32 result;
193 result = *(volatile u32 *)addr;
194 return result;
195}
196
Alexandru Gagniuc78706fd2013-06-03 13:58:10 -0500197/**
198 * \brief Representation of an MRS command
199 *
200 * This represents an MRS command as seen by the DIMM. This is not a memory
201 * address that can be read to generate an MRS command. The mapping of CPU
202 * to memory pins is hardware-dependent.
203 * \n
204 * The idea is to generalize the MRS code, and only need a hardware-specific
205 * function to map the MRS bits to CPU address bits. An MRS command can be
206 * sent like:
207 * @code{.c}
208 * u32 addr;
209 * mrs_cmd_t mrs;
210 * chipset_enable_mrs_command_mode();
211 * mrs = ddr3_get_mr2(rtt_wr, srt, asr, cwl)
212 * if (rank_has_mirrorred_pins)
213 * mrs = ddr3_mrs_mirror_pins(mrs);
214 * addr = chipset_specific_get_mrs_addr(mrs);
215 * volatile_read(addr);
216 * @endcode
217 *
218 * The MRS representation has the following structure:
219 * - cmd[15:0] = Address pins MA[15:0]
220 * - cmd[18:16] = Bank address BA[2:0]
221 */
222typedef u32 mrs_cmd_t;
223
224enum ddr3_mr0_precharge {
225 DDR3_MR0_PRECHARGE_SLOW = 0,
226 DDR3_MR0_PRECHARGE_FAST = 1,
227};
228enum ddr3_mr0_mode {
229 DDR3_MR0_MODE_NORMAL = 0,
230 DDR3_MR0_MODE_TEST = 1,
231};
232enum ddr3_mr0_dll_reset {
233 DDR3_MR0_DLL_RESET_NO = 0,
234 DDR3_MR0_DLL_RESET_YES = 1,
235};
236enum ddr3_mr0_burst_type {
237 DDR3_MR0_BURST_TYPE_SEQUENTIAL = 0,
238 DDR3_MR0_BURST_TYPE_INTERLEAVED = 1,
239};
240enum ddr3_mr0_burst_length {
241 DDR3_MR0_BURST_LENGTH_8 = 0,
242 DDR3_MR0_BURST_LENGTH_CHOP = 1,
243 DDR3_MR0_BURST_LENGTH_4 = 2,
244};
245mrs_cmd_t ddr3_get_mr0(enum ddr3_mr0_precharge precharge_pd,
246 u8 write_recovery,
247 enum ddr3_mr0_dll_reset dll_reset,
248 enum ddr3_mr0_mode mode,
249 u8 cas,
250 enum ddr3_mr0_burst_type interleaved_burst,
251 enum ddr3_mr0_burst_length burst_length);
252
253enum ddr3_mr1_qoff {
254 DDR3_MR1_QOFF_ENABLE = 0,
255 DDR3_MR1_QOFF_DISABLE = 1,
256};
257enum ddr3_mr1_tqds {
258 DDR3_MR1_TQDS_DISABLE = 0,
259 DDR3_MR1_TQDS_ENABLE = 1,
260};
261enum ddr3_mr1_write_leveling {
262 DDR3_MR1_WRLVL_DISABLE = 0,
263 DDR3_MR1_WRLVL_ENABLE = 1,
264};
265enum ddr3_mr1_rtt_nom {
266 DDR3_MR1_RTT_NOM_OFF = 0,
267 DDR3_MR1_RTT_NOM_RZQ4 = 1,
268 DDR3_MR1_RTT_NOM_RZQ2 = 2,
269 DDR3_MR1_RTT_NOM_RZQ6 = 3,
270 DDR3_MR1_RTT_NOM_RZQ12 = 4,
271 DDR3_MR1_RTT_NOM_RZQ8 = 5,
272};
273enum ddr3_mr1_additive_latency {
274 DDR3_MR1_AL_DISABLE = 0,
275 DDR3_MR1_AL_CL_MINUS_1 = 1,
276 DDR3_MR1_AL_CL_MINUS_2 = 2,
277};
278enum ddr3_mr1_ods {
279 DDR3_MR1_ODS_RZQ6 = 0,
280 DDR3_MR1_ODS_RZQ7 = 1,
281};
282enum ddr3_mr1_dll {
283 DDR3_MR1_DLL_ENABLE = 0,
284 DDR3_MR1_DLL_DISABLE = 1,
285};
286
287mrs_cmd_t ddr3_get_mr1(enum ddr3_mr1_qoff qoff,
288 enum ddr3_mr1_tqds tqds,
289 enum ddr3_mr1_rtt_nom rtt_nom,
290 enum ddr3_mr1_write_leveling write_leveling,
291 enum ddr3_mr1_ods output_drive_strenght,
292 enum ddr3_mr1_additive_latency additive_latency,
293 enum ddr3_mr1_dll dll_disable);
294
295enum ddr3_mr2_rttwr {
296 DDR3_MR2_RTTWR_OFF = 0,
297 DDR3_MR2_RTTWR_RZQ4 = 1,
298 DDR3_MR2_RTTWR_RZQ2 = 2,
299};
300enum ddr3_mr2_srt_range {
301 DDR3_MR2_SRT_NORMAL = 0,
302 DDR3_MR2_SRT_EXTENDED = 1,
303};
304enum ddr3_mr2_asr {
305 DDR3_MR2_ASR_MANUAL = 0,
306 DDR3_MR2_ASR_AUTO = 1,
307};
308
309mrs_cmd_t ddr3_get_mr2(enum ddr3_mr2_rttwr rtt_wr,
310 enum ddr3_mr2_srt_range extended_temp,
311 enum ddr3_mr2_asr self_refresh, u8 cas_cwl);
312
313mrs_cmd_t ddr3_get_mr3(char dataflow_from_mpr);
314mrs_cmd_t ddr3_mrs_mirror_pins(mrs_cmd_t cmd);
315
Martin Rothfd277d82016-01-11 12:47:30 -0700316#endif /* DEVICE_DRAM_DDR3L_H */