blob: f3605b289d387dada865ae0b154600329a27247b [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Patrick Rudolph6e53ae62017-01-31 19:43:17 +01002
3/*
4 * JEDEC Standard No. 21-C
5 * Annex J: Annex J: Serial Presence Detects for DDR2 SDRAM (Revision 1.3)
6 */
7
8#ifndef DEVICE_DRAM_DDR2L_H
9#define DEVICE_DRAM_DDR2L_H
10
11/**
12 * @file ddr2.h
13 *
14 * \brief Utilities for decoding DDR2 SPDs
15 */
16
17#include <stdint.h>
18#include <spd.h>
Arthur Heymansfc31e442018-02-12 15:12:34 +010019#include <device/dram/common.h>
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010020
Martin Roth58964ff2023-10-23 09:59:09 -060021/** Maximum SPD size supported */
22#define SPD_SIZE_MAX_DDR2 128
23
Elyes Haouas5a047462022-12-28 11:43:49 +010024/* Byte 20 [5:0]: DDR2 Module type information */
Arthur Heymansfc31e442018-02-12 15:12:34 +010025enum spd_dimm_type_ddr2 {
Elyes Haouas5a047462022-12-28 11:43:49 +010026 SPD_DDR2_DIMM_TYPE_UNDEFINED = 0x00,
27 SPD_DDR2_DIMM_TYPE_RDIMM = 0x01,
28 SPD_DDR2_DIMM_TYPE_UDIMM = 0x02,
29 SPD_DDR2_DIMM_TYPE_SO_DIMM = 0x04,
Arthur Heymansfc31e442018-02-12 15:12:34 +010030 SPD_DDR2_DIMM_TYPE_72B_SO_CDIMM = 0x06,
31 SPD_DDR2_DIMM_TYPE_72B_SO_RDIMM = 0x07,
32 SPD_DDR2_DIMM_TYPE_MICRO_DIMM = 0x08,
33 SPD_DDR2_DIMM_TYPE_MINI_RDIMM = 0x10,
34 SPD_DDR2_DIMM_TYPE_MINI_UDIMM = 0x20,
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010035 /* Masks to bits 5:0 to give the dimm type */
Arthur Heymansfc31e442018-02-12 15:12:34 +010036 SPD_DDR2_DIMM_TYPE_MASK = 0x3f,
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010037};
38
39/**
40 * \brief DIMM flags
41 *
42 * Characteristic flags for the DIMM, as presented by the SPD
43 */
Arthur Heymansfc31e442018-02-12 15:12:34 +010044union dimm_flags_ddr2_st {
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010045 /* The whole point of the union/struct construct is to allow us to clear
46 * all the bits with one line: flags.raw = 0.
47 * We do not care how these bits are ordered */
48 struct {
49 /* Module can work at 5.00V */
Martin Rothfc2047b2020-11-11 09:18:36 -070050 unsigned int operable_5_00V:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010051 /* Module can work at 3.33V */
Martin Rothfc2047b2020-11-11 09:18:36 -070052 unsigned int operable_3_33V:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010053 /* Module can work at 2.50V */
Martin Rothfc2047b2020-11-11 09:18:36 -070054 unsigned int operable_2_50V:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010055 /* Module can work at 1.80V - All DIMMS must be 1.8V operable */
Martin Rothfc2047b2020-11-11 09:18:36 -070056 unsigned int operable_1_80V:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010057 /* Module can work at 1.50V */
Martin Rothfc2047b2020-11-11 09:18:36 -070058 unsigned int operable_1_50V:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010059 /* Module can work at 1.35V */
Martin Rothfc2047b2020-11-11 09:18:36 -070060 unsigned int operable_1_35V:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010061 /* Module can work at 1.20V */
Martin Rothfc2047b2020-11-11 09:18:36 -070062 unsigned int operable_1_25V:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010063 /* Has an 8-bit bus extension, meaning the DIMM supports ECC */
Martin Rothfc2047b2020-11-11 09:18:36 -070064 unsigned int is_ecc:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010065 /* Supports weak driver */
Martin Rothfc2047b2020-11-11 09:18:36 -070066 unsigned int weak_driver:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010067 /* Supports terminating at 50 Ohm */
Martin Rothfc2047b2020-11-11 09:18:36 -070068 unsigned int terminate_50ohms:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010069 /* Partial Array Self Refresh */
Martin Rothfc2047b2020-11-11 09:18:36 -070070 unsigned int pasr:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010071 /* Supports burst length 8 */
Martin Rothfc2047b2020-11-11 09:18:36 -070072 unsigned int bl8:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010073 /* Supports burst length 4 */
Martin Rothfc2047b2020-11-11 09:18:36 -070074 unsigned int bl4:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010075 /* DIMM Package is stack */
Martin Rothfc2047b2020-11-11 09:18:36 -070076 unsigned int stacked:1;
Arthur Heymans7eb01572017-09-21 08:28:23 +020077 /* the assembly supports self refresh */
Martin Rothfc2047b2020-11-11 09:18:36 -070078 unsigned int self_refresh:1;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010079 };
80 unsigned int raw;
81};
82
83/**
84 * \brief DIMM characteristics
85 *
86 * The characteristics of each DIMM, as presented by the SPD
87 */
Arthur Heymansfc31e442018-02-12 15:12:34 +010088struct dimm_attr_ddr2_st {
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010089 enum spd_memory_type dram_type;
Arthur Heymansfc31e442018-02-12 15:12:34 +010090 enum spd_dimm_type_ddr2 dimm_type;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010091 /* BCD SPD revision */
92 u8 rev;
93 /* Supported CAS mask, bit 0 == CL0 .. bit7 == CL7 */
94 u8 cas_supported;
Martin Roth3e25f852023-09-04 15:37:07 -060095 /* Maximum clock to data cycle times for various CAS.
Patrick Rudolph6e53ae62017-01-31 19:43:17 +010096 * Fields 0 and 1 are unused. */
97 u32 cycle_time[8];
98 /* Maximum data access times for various CAS.
99 * Fields 0 and 1 are unused. */
100 u32 access_time[8];
101 /* Flags extracted from SPD */
Arthur Heymansfc31e442018-02-12 15:12:34 +0100102 union dimm_flags_ddr2_st flags;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100103 /* Number of banks */
104 u8 banks;
105 /* SDRAM width */
106 u8 width;
107 /* Module width */
108 u8 mod_width;
109 /* Number of ranks */
110 u8 ranks;
111 /* Number or row address bits */
112 u8 row_bits;
113 /* Number or column address bits */
114 u8 col_bits;
115 /* Number of PLLs on module */
116 u8 plls;
117 /* Size of module in MiB */
118 u16 size_mb;
119 /* Size of one rank in MiB */
120 u16 ranksize_mb;
121 /* Latencies are in units of 1/256 ns */
122 u32 tCK;
123 u32 tWR;
124 u32 tRCD;
125 u32 tRRD;
126 u32 tRP;
127 u32 tRAS;
128 u32 tIS;
129 u32 tIH;
130 u32 tDS;
131 u32 tDH;
132
133 u32 tRC;
134 u32 tRFC;
135 u32 tWTR;
136 u32 tRTP;
137 u32 tDQSQ;
138 u32 tQHS;
139
140 /* Latencies are in units of 1/256 us */
141 u32 tPLL;
142 u32 tRR;
143
Arthur Heymansb5d4dd12017-09-25 12:47:41 +0200144 u8 checksum;
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100145 /* Manufacturer ID */
146 u32 manufacturer_id;
147 /* ASCII part number - NULL terminated */
148 u8 part_number[17];
149 /* Year manufactured */
150 u16 year;
151 /* Week manufactured */
152 u8 weeks;
153 /* Unique serial number */
154 u32 serial;
155};
156
Arthur Heymansfc31e442018-02-12 15:12:34 +0100157int spd_dimm_is_registered_ddr2(enum spd_dimm_type_ddr2 type);
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100158u8 spd_ddr2_calc_checksum(u8 *spd, int len);
159u32 spd_decode_spd_size_ddr2(u8 byte0);
160u32 spd_decode_eeprom_size_ddr2(u8 byte1);
Arthur Heymansfc31e442018-02-12 15:12:34 +0100161int spd_decode_ddr2(struct dimm_attr_ddr2_st *dimm, u8 spd[SPD_SIZE_MAX_DDR2]);
162void dram_print_spd_ddr2(const struct dimm_attr_ddr2_st *dimm);
Arthur Heymans3397aa12017-03-01 20:10:55 +0100163void normalize_tck(u32 *tclk);
164u8 spd_get_msbs(u8 c);
Arthur Heymans97b337b2018-01-22 01:26:53 +0100165u16 spd_ddr2_calc_unique_crc(const u8 *spd, int len);
Patrick Rudolph6e53ae62017-01-31 19:43:17 +0100166
167#endif /* DEVICE_DRAM_DDR2L_H */