summaryrefslogtreecommitdiffstats
path: root/drivers/ddr/fsl/ddr4_dimm_params.c
blob: 2418dca6ab9468c729ecd3bcccf81d1d69f05a31 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/*
 * Copyright 2014 Freescale Semiconductor, Inc.
 *
 * calculate the organization and timing parameter
 * from ddr3 spd, please refer to the spec
 * JEDEC standard No.21-C 4_01_02_12R23A.pdf
 *
 *
 */

#include <common.h>
#include <fsl_ddr_sdram.h>

#include <fsl_ddr.h>

/*
 * Calculate the Density of each Physical Rank.
 * Returned size is in bytes.
 *
 * Total DIMM size =
 * sdram capacity(bit) / 8 * primary bus width / sdram width
 *                     * Logical Ranks per DIMM
 *
 * where: sdram capacity  = spd byte4[3:0]
 *        primary bus width = spd byte13[2:0]
 *        sdram width = spd byte12[2:0]
 *        Logical Ranks per DIMM = spd byte12[5:3] for SDP, DDP, QDP
 *                                 spd byte12{5:3] * spd byte6[6:4] for 3DS
 *
 * To simplify each rank size = total DIMM size / Number of Package Ranks
 * where Number of Package Ranks = spd byte12[5:3]
 *
 * SPD byte4 - sdram density and banks
 *	bit[3:0]	size(bit)	size(byte)
 *	0000		256Mb		32MB
 *	0001		512Mb		64MB
 *	0010		1Gb		128MB
 *	0011		2Gb		256MB
 *	0100		4Gb		512MB
 *	0101		8Gb		1GB
 *	0110		16Gb		2GB
 *      0111		32Gb		4GB
 *
 * SPD byte13 - module memory bus width
 *	bit[2:0]	primary bus width
 *	000		8bits
 *	001		16bits
 *	010		32bits
 *	011		64bits
 *
 * SPD byte12 - module organization
 *	bit[2:0]	sdram device width
 *	000		4bits
 *	001		8bits
 *	010		16bits
 *	011		32bits
 *
 * SPD byte12 - module organization
 *	bit[5:3]	number of package ranks per DIMM
 *	000		1
 *	001		2
 *	010		3
 *	011		4
 *
 * SPD byte6 - SDRAM package type
 *	bit[6:4]	Die count
 *	000		1
 *	001		2
 *	010		3
 *	011		4
 *	100		5
 *	101		6
 *	110		7
 *	111		8
 *
 * SPD byte6 - SRAM package type
 *	bit[1:0]	Signal loading
 *	00		Not specified
 *	01		Multi load stack
 *	10		Sigle load stack (3DS)
 *	11		Reserved
 */
static unsigned long long
compute_ranksize(const struct ddr4_spd_eeprom_s *spd)
{
	unsigned long long bsize;

	int nbit_sdram_cap_bsize = 0;
	int nbit_primary_bus_width = 0;
	int nbit_sdram_width = 0;
	int die_count = 0;
	bool package_3ds;

	if ((spd->density_banks & 0xf) <= 7)
		nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28;
	if ((spd->bus_width & 0x7) < 4)
		nbit_primary_bus_width = (spd->bus_width & 0x7) + 3;
	if ((spd->organization & 0x7) < 4)
		nbit_sdram_width = (spd->organization & 0x7) + 2;
	package_3ds = (spd->package_type & 0x3) == 0x2;
	if (package_3ds)
		die_count = (spd->package_type >> 4) & 0x7;

	bsize = 1ULL << (nbit_sdram_cap_bsize - 3 +
			 nbit_primary_bus_width - nbit_sdram_width +
			 die_count);

	debug("DDR: DDR III rank density = 0x%16llx\n", bsize);

	return bsize;
}

#define spd_to_ps(mtb, ftb)	\
	(mtb * pdimm->mtb_ps + (ftb * pdimm->ftb_10th_ps) / 10)
/*
 * ddr_compute_dimm_parameters for DDR4 SPD
 *
 * Compute DIMM parameters based upon the SPD information in spd.
 * Writes the results to the dimm_params_t structure pointed by pdimm.
 *
 */
unsigned int
ddr_compute_dimm_parameters(const generic_spd_eeprom_t *spd,
			    dimm_params_t *pdimm,
			    unsigned int dimm_number)
{
	unsigned int retval;
	int i;

	if (spd->mem_type) {
		if (spd->mem_type != SPD_MEMTYPE_DDR4) {
			printf("DIMM %u: is not a DDR4 SPD.\n", dimm_number);
			return 1;
		}
	} else {
		memset(pdimm, 0, sizeof(dimm_params_t));
		return 1;
	}

	retval = ddr4_spd_check(spd);
	if (retval) {
		printf("DIMM %u: failed checksum\n", dimm_number);
		return 2;
	}

	/*
	 * The part name in ASCII in the SPD EEPROM is not null terminated.
	 * Guarantee null termination here by presetting all bytes to 0
	 * and copying the part name in ASCII from the SPD onto it
	 */
	memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
	if ((spd->info_size_crc & 0xF) > 2)
		memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);

	/* DIMM organization parameters */
	pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1;
	pdimm->rank_density = compute_ranksize(spd);
	pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
	pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7));
	if ((spd->bus_width >> 3) & 0x3)
		pdimm->ec_sdram_width = 8;
	else
		pdimm->ec_sdram_width = 0;
	pdimm->data_width = pdimm->primary_sdram_width
			  + pdimm->ec_sdram_width;
	pdimm->device_width = 1 << ((spd->organization & 0x7) + 2);

	/* These are the types defined by the JEDEC SPD spec */
	pdimm->mirrored_dimm = 0;
	pdimm->registered_dimm = 0;
	switch (spd->module_type & DDR4_SPD_MODULETYPE_MASK) {
	case DDR4_SPD_MODULETYPE_RDIMM:
		/* Registered/buffered DIMMs */
		pdimm->registered_dimm = 1;
		break;

	case DDR4_SPD_MODULETYPE_UDIMM:
	case DDR4_SPD_MODULETYPE_SO_DIMM:
		/* Unbuffered DIMMs */
		if (spd->mod_section.unbuffered.addr_mapping & 0x1)
			pdimm->mirrored_dimm = 1;
		break;

	default:
		printf("unknown module_type 0x%02X\n", spd->module_type);
		return 1;
	}

	/* SDRAM device parameters */
	pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12;
	pdimm->n_col_addr = (spd->addressing & 0x7) + 9;
	pdimm->bank_addr_bits = (spd->density_banks >> 4) & 0x3;
	pdimm->bank_group_bits = (spd->density_banks >> 6) & 0x3;

	/*
	 * The SPD spec has not the ECC bit,
	 * We consider the DIMM as ECC capability
	 * when the extension bus exist
	 */
	if (pdimm->ec_sdram_width)
		pdimm->edc_config = 0x02;
	else
		pdimm->edc_config = 0x00;

	/*
	 * The SPD spec has not the burst length byte
	 * but DDR4 spec has nature BL8 and BC4,
	 * BL8 -bit3, BC4 -bit2
	 */
	pdimm->burst_lengths_bitmask = 0x0c;
	pdimm->row_density = __ilog2(pdimm->rank_density);

	/* MTB - medium timebase
	 * The MTB in the SPD spec is 125ps,
	 *
	 * FTB - fine timebase
	 * use 1/10th of ps as our unit to avoid floating point
	 * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps
	 */
	if ((spd->timebases & 0xf) == 0x0) {
		pdimm->mtb_ps = 125;
		pdimm->ftb_10th_ps = 10;

	} else {
		printf("Unknown Timebases\n");
	}

	/* sdram minimum cycle time */
	pdimm->tckmin_x_ps = spd_to_ps(spd->tck_min, spd->fine_tck_min);

	/* sdram max cycle time */
	pdimm->tckmax_ps = spd_to_ps(spd->tck_max, spd->fine_tck_max);

	/*
	 * CAS latency supported
	 * bit0 - CL7
	 * bit4 - CL11
	 * bit8 - CL15
	 * bit12- CL19
	 * bit16- CL23
	 */
	pdimm->caslat_x  = (spd->caslat_b1 << 7)	|
			   (spd->caslat_b2 << 15)	|
			   (spd->caslat_b3 << 23);

	BUG_ON(spd->caslat_b4 != 0);

	/*
	 * min CAS latency time
	 */
	pdimm->taa_ps = spd_to_ps(spd->taa_min, spd->fine_taa_min);

	/*
	 * min RAS to CAS delay time
	 */
	pdimm->trcd_ps = spd_to_ps(spd->trcd_min, spd->fine_trcd_min);

	/*
	 * Min Row Precharge Delay Time
	 */
	pdimm->trp_ps = spd_to_ps(spd->trp_min, spd->fine_trp_min);

	/* min active to precharge delay time */
	pdimm->tras_ps = (((spd->tras_trc_ext & 0xf) << 8) +
			  spd->tras_min_lsb) * pdimm->mtb_ps;

	/* min active to actice/refresh delay time */
	pdimm->trc_ps = spd_to_ps((((spd->tras_trc_ext & 0xf0) << 4) +
				   spd->trc_min_lsb), spd->fine_trc_min);
	/* Min Refresh Recovery Delay Time */
	pdimm->trfc1_ps = ((spd->trfc1_min_msb << 8) | (spd->trfc1_min_lsb)) *
		       pdimm->mtb_ps;
	pdimm->trfc2_ps = ((spd->trfc2_min_msb << 8) | (spd->trfc2_min_lsb)) *
		       pdimm->mtb_ps;
	pdimm->trfc4_ps = ((spd->trfc4_min_msb << 8) | (spd->trfc4_min_lsb)) *
			pdimm->mtb_ps;
	/* min four active window delay time */
	pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) *
			pdimm->mtb_ps;

	/* min row active to row active delay time, different bank group */
	pdimm->trrds_ps = spd_to_ps(spd->trrds_min, spd->fine_trrds_min);
	/* min row active to row active delay time, same bank group */
	pdimm->trrdl_ps = spd_to_ps(spd->trrdl_min, spd->fine_trrdl_min);
	/* min CAS to CAS Delay Time (tCCD_Lmin), same bank group */
	pdimm->tccdl_ps = spd_to_ps(spd->tccdl_min, spd->fine_tccdl_min);

	/*
	 * Average periodic refresh interval
	 * tREFI = 7.8 us at normal temperature range
	 */
	pdimm->refresh_rate_ps = 7800000;

	for (i = 0; i < 18; i++)
		pdimm->dq_mapping[i] = spd->mapping[i];

	pdimm->dq_mapping_ors = ((spd->mapping[0] >> 6) & 0x3) == 0 ? 1 : 0;

	return 0;
}
OpenPOWER on IntegriCloud