1*2b4ffbf6SChris Packham /* SPDX-License-Identifier: GPL-2.0 */
2*2b4ffbf6SChris Packham /*
3*2b4ffbf6SChris Packham  * Copyright (C) Marvell International Ltd. and its affiliates
4*2b4ffbf6SChris Packham  */
5*2b4ffbf6SChris Packham 
6*2b4ffbf6SChris Packham #ifndef _MV_DDR_SPD_H
7*2b4ffbf6SChris Packham #define _MV_DDR_SPD_H
8*2b4ffbf6SChris Packham 
9*2b4ffbf6SChris Packham #include "mv_ddr_topology.h"
10*2b4ffbf6SChris Packham 
11*2b4ffbf6SChris Packham /*
12*2b4ffbf6SChris Packham  * Based on JEDEC Standard No. 21-C, 4.1.2.L-4:
13*2b4ffbf6SChris Packham  * Serial Presence Detect (SPD) for DDR4 SDRAM Modules
14*2b4ffbf6SChris Packham  */
15*2b4ffbf6SChris Packham 
16*2b4ffbf6SChris Packham /* block 0: base configuration and dram parameters */
17*2b4ffbf6SChris Packham #define MV_DDR_SPD_DATA_BLOCK0_SIZE		128
18*2b4ffbf6SChris Packham /* block 1: module specific parameters sub-block */
19*2b4ffbf6SChris Packham #define MV_DDR_SPD_DATA_BLOCK1M_SIZE		64
20*2b4ffbf6SChris Packham /* block 1: hybrid memory parameters sub-block */
21*2b4ffbf6SChris Packham #define MV_DDR_SPD_DATA_BLOCK1H_SIZE		64
22*2b4ffbf6SChris Packham /* block 2: extended function parameter block */
23*2b4ffbf6SChris Packham #define MV_DDR_SPD_DATA_BLOCK2E_SIZE		64
24*2b4ffbf6SChris Packham /* block 2: manufacturing information */
25*2b4ffbf6SChris Packham #define MV_DDR_SPD_DATA_BLOCK2M_SIZE		64
26*2b4ffbf6SChris Packham /* block 3: end user programmable */
27*2b4ffbf6SChris Packham #define MV_DDR_SPD_DATA_BLOCK3_SIZE		128
28*2b4ffbf6SChris Packham 
29*2b4ffbf6SChris Packham #define MV_DDR_SPD_DEV_TYPE_DDR4		0xc
30*2b4ffbf6SChris Packham #define MV_DDR_SPD_MODULE_TYPE_UDIMM		0x2
31*2b4ffbf6SChris Packham #define MV_DDR_SPD_MODULE_TYPE_SO_DIMM		0x3
32*2b4ffbf6SChris Packham #define MV_DDR_SPD_MODULE_TYPE_MINI_UDIMM	0x6
33*2b4ffbf6SChris Packham #define MV_DDR_SPD_MODULE_TYPE_72BIT_SO_UDIMM	0x9
34*2b4ffbf6SChris Packham #define MV_DDR_SPD_MODULE_TYPE_16BIT_SO_DIMM	0xc
35*2b4ffbf6SChris Packham #define MV_DDR_SPD_MODULE_TYPE_32BIT_SO_DIMM	0xd
36*2b4ffbf6SChris Packham 
37*2b4ffbf6SChris Packham /*
38*2b4ffbf6SChris Packham  * TODO: For now, the struct contains block 0 & block 1 with module specific
39*2b4ffbf6SChris Packham  * parameters for unbuffered memory module types only.
40*2b4ffbf6SChris Packham  */
41*2b4ffbf6SChris Packham union mv_ddr_spd_data {
42*2b4ffbf6SChris Packham 	unsigned char all_bytes[MV_DDR_SPD_DATA_BLOCK0_SIZE +
43*2b4ffbf6SChris Packham 				MV_DDR_SPD_DATA_BLOCK1M_SIZE];
44*2b4ffbf6SChris Packham 	struct {
45*2b4ffbf6SChris Packham 		/* block 0 */
46*2b4ffbf6SChris Packham 		union { /* num of bytes used/num of bytes in spd device/crc coverage */
47*2b4ffbf6SChris Packham 			unsigned char all_bits;
48*2b4ffbf6SChris Packham 			struct {
49*2b4ffbf6SChris Packham 				unsigned char spd_bytes_used:4,
50*2b4ffbf6SChris Packham 					spd_bytes_total:3,
51*2b4ffbf6SChris Packham 					reserved:1;
52*2b4ffbf6SChris Packham 			} bit_fields;
53*2b4ffbf6SChris Packham 		} byte_0;
54*2b4ffbf6SChris Packham 		union { /* spd revision */
55*2b4ffbf6SChris Packham 			unsigned char all_bits;
56*2b4ffbf6SChris Packham 			struct {
57*2b4ffbf6SChris Packham 				unsigned char addtions_level:4,
58*2b4ffbf6SChris Packham 					encoding_level:4;
59*2b4ffbf6SChris Packham 			} bit_fields;
60*2b4ffbf6SChris Packham 		} byte_1;
61*2b4ffbf6SChris Packham 		unsigned char  byte_2; /* key_byte/dram device type */
62*2b4ffbf6SChris Packham 		union { /* key byte/module type */
63*2b4ffbf6SChris Packham 			unsigned char all_bits;
64*2b4ffbf6SChris Packham 			struct {
65*2b4ffbf6SChris Packham 				unsigned char module_type:4,
66*2b4ffbf6SChris Packham 					hybrid_media:3,
67*2b4ffbf6SChris Packham 					hybrid:1;
68*2b4ffbf6SChris Packham 			} bit_fields;
69*2b4ffbf6SChris Packham 		} byte_3;
70*2b4ffbf6SChris Packham 		union { /* sdram density & banks */
71*2b4ffbf6SChris Packham 			unsigned char all_bits;
72*2b4ffbf6SChris Packham 			struct {
73*2b4ffbf6SChris Packham 				unsigned char die_capacity:4,
74*2b4ffbf6SChris Packham 					bank_address:2,
75*2b4ffbf6SChris Packham 					bank_group:2;
76*2b4ffbf6SChris Packham 			} bit_fields;
77*2b4ffbf6SChris Packham 		} byte_4;
78*2b4ffbf6SChris Packham 		union { /* sdram addressing */
79*2b4ffbf6SChris Packham 			unsigned char all_bits;
80*2b4ffbf6SChris Packham 			struct {
81*2b4ffbf6SChris Packham 				unsigned char col_address:3,
82*2b4ffbf6SChris Packham 					row_address:3,
83*2b4ffbf6SChris Packham 					reserved:2;
84*2b4ffbf6SChris Packham 			} bit_fields;
85*2b4ffbf6SChris Packham 		} byte_5;
86*2b4ffbf6SChris Packham 		union { /* sdram package type */
87*2b4ffbf6SChris Packham 			unsigned char all_bits;
88*2b4ffbf6SChris Packham 			struct {
89*2b4ffbf6SChris Packham 				unsigned char signal_loading:2,
90*2b4ffbf6SChris Packham 					reserved:2,
91*2b4ffbf6SChris Packham 					die_count:3,
92*2b4ffbf6SChris Packham 					sdram_package_type:1;
93*2b4ffbf6SChris Packham 			} bit_fields;
94*2b4ffbf6SChris Packham 		} byte_6;
95*2b4ffbf6SChris Packham 		union { /* sdram optional features */
96*2b4ffbf6SChris Packham 			unsigned char all_bits;
97*2b4ffbf6SChris Packham 			struct {
98*2b4ffbf6SChris Packham 				unsigned char mac:4, /* max activate count */
99*2b4ffbf6SChris Packham 					t_maw:2, /* max activate window */
100*2b4ffbf6SChris Packham 					reserved:2; /* all 0s */
101*2b4ffbf6SChris Packham 			} bit_fields;
102*2b4ffbf6SChris Packham 		} byte_7;
103*2b4ffbf6SChris Packham 		unsigned char byte_8; /* sdram thermal & refresh options; reserved; 0x00 */
104*2b4ffbf6SChris Packham 		union { /* other sdram optional features */
105*2b4ffbf6SChris Packham 			unsigned char all_bits;
106*2b4ffbf6SChris Packham 			struct {
107*2b4ffbf6SChris Packham 				unsigned char reserved:5, /* all 0s */
108*2b4ffbf6SChris Packham 					soft_ppr:1,
109*2b4ffbf6SChris Packham 					ppr:2; /* post package repair */
110*2b4ffbf6SChris Packham 			} bit_fields;
111*2b4ffbf6SChris Packham 		} byte_9;
112*2b4ffbf6SChris Packham 		union { /* secondary sdram package type */
113*2b4ffbf6SChris Packham 			unsigned char all_bits;
114*2b4ffbf6SChris Packham 			struct {
115*2b4ffbf6SChris Packham 				unsigned char signal_loading:2,
116*2b4ffbf6SChris Packham 					density_ratio:2, /* dram density ratio */
117*2b4ffbf6SChris Packham 					die_count:3,
118*2b4ffbf6SChris Packham 					sdram_package_type:1;
119*2b4ffbf6SChris Packham 			} bit_fields;
120*2b4ffbf6SChris Packham 		} byte_10;
121*2b4ffbf6SChris Packham 		union { /* module nominal voltage, vdd */
122*2b4ffbf6SChris Packham 			unsigned char all_bits;
123*2b4ffbf6SChris Packham 			struct {
124*2b4ffbf6SChris Packham 				unsigned char operable:1,
125*2b4ffbf6SChris Packham 					endurant:1,
126*2b4ffbf6SChris Packham 					reserved:5; /* all 0s */
127*2b4ffbf6SChris Packham 			} bit_fields;
128*2b4ffbf6SChris Packham 		} byte_11;
129*2b4ffbf6SChris Packham 		union { /* module organization*/
130*2b4ffbf6SChris Packham 			unsigned char all_bits;
131*2b4ffbf6SChris Packham 			struct {
132*2b4ffbf6SChris Packham 				unsigned char device_width:3,
133*2b4ffbf6SChris Packham 					dimm_pkg_ranks_num:3, /* package ranks per dimm number */
134*2b4ffbf6SChris Packham 					rank_mix:1,
135*2b4ffbf6SChris Packham 					reserved:1; /* 0 */
136*2b4ffbf6SChris Packham 			} bit_fields;
137*2b4ffbf6SChris Packham 		} byte_12;
138*2b4ffbf6SChris Packham 		union { /* module memory bus width */
139*2b4ffbf6SChris Packham 			unsigned char all_bits;
140*2b4ffbf6SChris Packham 			struct {
141*2b4ffbf6SChris Packham 				unsigned char primary_bus_width:3, /* in bits */
142*2b4ffbf6SChris Packham 					bus_width_ext:2, /* in bits */
143*2b4ffbf6SChris Packham 					reserved:3; /* all 0s */
144*2b4ffbf6SChris Packham 			} bit_fields;
145*2b4ffbf6SChris Packham 		} byte_13;
146*2b4ffbf6SChris Packham 		union { /* module thernal sensor */
147*2b4ffbf6SChris Packham 			unsigned char all_bits;
148*2b4ffbf6SChris Packham 			struct {
149*2b4ffbf6SChris Packham 				unsigned char reserved:7,
150*2b4ffbf6SChris Packham 					thermal_sensor:1;
151*2b4ffbf6SChris Packham 			} bit_fields;
152*2b4ffbf6SChris Packham 		} byte_14;
153*2b4ffbf6SChris Packham 		union { /* extended module type */
154*2b4ffbf6SChris Packham 			unsigned char all_bits;
155*2b4ffbf6SChris Packham 			struct {
156*2b4ffbf6SChris Packham 				unsigned char ext_base_module_type:4,
157*2b4ffbf6SChris Packham 					reserved:4; /* all 0s */
158*2b4ffbf6SChris Packham 			} bit_fields;
159*2b4ffbf6SChris Packham 		} byte_15;
160*2b4ffbf6SChris Packham 		unsigned char byte_16; /* reserved; 0x00 */
161*2b4ffbf6SChris Packham 		union { /* timebases */
162*2b4ffbf6SChris Packham 			unsigned char all_bits;
163*2b4ffbf6SChris Packham 			struct {
164*2b4ffbf6SChris Packham 				unsigned char ftb:2, /* fine timebase */
165*2b4ffbf6SChris Packham 					mtb:2, /* medium timebase */
166*2b4ffbf6SChris Packham 					reserved:4; /* all 0s */
167*2b4ffbf6SChris Packham 			} bit_fields;
168*2b4ffbf6SChris Packham 		} byte_17;
169*2b4ffbf6SChris Packham 		unsigned char byte_18; /* sdram min cycle time (t ck avg min), mtb */
170*2b4ffbf6SChris Packham 		unsigned char byte_19; /* sdram max cycle time (t ck avg max), mtb */
171*2b4ffbf6SChris Packham 		unsigned char byte_20; /* cas latencies supported, first byte */
172*2b4ffbf6SChris Packham 		unsigned char byte_21; /* cas latencies supported, second byte */
173*2b4ffbf6SChris Packham 		unsigned char byte_22; /* cas latencies supported, third byte */
174*2b4ffbf6SChris Packham 		unsigned char byte_23; /* cas latencies supported, fourth byte */
175*2b4ffbf6SChris Packham 		unsigned char byte_24; /* min cas latency time (t aa min), mtb */
176*2b4ffbf6SChris Packham 		unsigned char byte_25; /* min ras to cas delay time (t rcd min), mtb */
177*2b4ffbf6SChris Packham 		unsigned char byte_26; /* min row precharge delay time (t rp min), mtb */
178*2b4ffbf6SChris Packham 		union { /* upper nibbles for t ras min & t rc min */
179*2b4ffbf6SChris Packham 			unsigned char all_bits;
180*2b4ffbf6SChris Packham 			struct {
181*2b4ffbf6SChris Packham 				unsigned char t_ras_min_msn:4, /* t ras min most significant nibble */
182*2b4ffbf6SChris Packham 					t_rc_min_msn:4; /* t rc min most significant nibble */
183*2b4ffbf6SChris Packham 			} bit_fields;
184*2b4ffbf6SChris Packham 		} byte_27;
185*2b4ffbf6SChris Packham 		unsigned char byte_28; /* min active to precharge delay time (t ras min), l-s-byte, mtb */
186*2b4ffbf6SChris Packham 		unsigned char byte_29; /* min active to active/refresh delay time (t rc min), l-s-byte, mtb */
187*2b4ffbf6SChris Packham 		unsigned char byte_30; /* min refresh recovery delay time (t rfc1 min), l-s-byte, mtb */
188*2b4ffbf6SChris Packham 		unsigned char byte_31; /* min refresh recovery delay time (t rfc1 min), m-s-byte, mtb */
189*2b4ffbf6SChris Packham 		unsigned char byte_32; /* min refresh recovery delay time (t rfc2 min), l-s-byte, mtb */
190*2b4ffbf6SChris Packham 		unsigned char byte_33; /* min refresh recovery delay time (t rfc2 min), m-s-byte, mtb */
191*2b4ffbf6SChris Packham 		unsigned char byte_34; /* min refresh recovery delay time (t rfc4 min), l-s-byte, mtb */
192*2b4ffbf6SChris Packham 		unsigned char byte_35; /* min refresh recovery delay time (t rfc4 min), m-s-byte, mtb */
193*2b4ffbf6SChris Packham 		union { /* upper nibble for t faw */
194*2b4ffbf6SChris Packham 			unsigned char all_bits;
195*2b4ffbf6SChris Packham 			struct {
196*2b4ffbf6SChris Packham 				unsigned char t_faw_min_msn:4, /* t faw min most significant nibble */
197*2b4ffbf6SChris Packham 					reserved:4;
198*2b4ffbf6SChris Packham 			} bit_fields;
199*2b4ffbf6SChris Packham 		} byte_36;
200*2b4ffbf6SChris Packham 		unsigned char byte_37; /* min four activate window delay time (t faw min), l-s-byte, mtb */
201*2b4ffbf6SChris Packham 		/* byte 38: min activate to activate delay time (t rrd_s min), diff bank group, mtb */
202*2b4ffbf6SChris Packham 		unsigned char byte_38;
203*2b4ffbf6SChris Packham 		/* byte 39: min activate to activate delay time (t rrd_l min), same bank group, mtb */
204*2b4ffbf6SChris Packham 		unsigned char byte_39;
205*2b4ffbf6SChris Packham 		unsigned char byte_40; /* min cas to cas delay time (t ccd_l min), same bank group, mtb */
206*2b4ffbf6SChris Packham 		union { /* upper nibble for t wr min */
207*2b4ffbf6SChris Packham 			unsigned char all_bits;
208*2b4ffbf6SChris Packham 			struct {
209*2b4ffbf6SChris Packham 				unsigned char t_wr_min_msn:4, /* t wr min most significant nibble */
210*2b4ffbf6SChris Packham 					reserved:4;
211*2b4ffbf6SChris Packham 			} bit_fields;
212*2b4ffbf6SChris Packham 		} byte_41;
213*2b4ffbf6SChris Packham 		unsigned char byte_42; /* min write recovery time (t wr min) */
214*2b4ffbf6SChris Packham 		union { /* upper nibbles for t wtr min */
215*2b4ffbf6SChris Packham 			unsigned char all_bits;
216*2b4ffbf6SChris Packham 			struct {
217*2b4ffbf6SChris Packham 				unsigned char t_wtr_s_min_msn:4, /* t wtr s min most significant nibble */
218*2b4ffbf6SChris Packham 					t_wtr_l_min_msn:4; /* t wtr l min most significant nibble */
219*2b4ffbf6SChris Packham 			} bit_fields;
220*2b4ffbf6SChris Packham 		} byte_43;
221*2b4ffbf6SChris Packham 		unsigned char byte_44; /* min write to read time (t wtr s min), diff bank group, mtb */
222*2b4ffbf6SChris Packham 		unsigned char byte_45; /* min write to read time (t wtr l min), same bank group, mtb */
223*2b4ffbf6SChris Packham 		unsigned char bytes_46_59[14]; /* reserved; all 0s */
224*2b4ffbf6SChris Packham 		unsigned char bytes_60_77[18]; /* TODO: connector to sdram bit mapping */
225*2b4ffbf6SChris Packham 		unsigned char bytes_78_116[39]; /* reserved; all 0s */
226*2b4ffbf6SChris Packham 		/* fine offset for min cas to cas delay time (t ccd_l min), same bank group, ftb */
227*2b4ffbf6SChris Packham 		unsigned char byte_117;
228*2b4ffbf6SChris Packham 		/* fine offset for min activate to activate delay time (t rrd_l min), same bank group, ftb */
229*2b4ffbf6SChris Packham 		unsigned char byte_118;
230*2b4ffbf6SChris Packham 		/* fine offset for min activate to activate delay time (t rrd_s min), diff bank group, ftb */
231*2b4ffbf6SChris Packham 		unsigned char byte_119;
232*2b4ffbf6SChris Packham 		/* fine offset for min active to active/refresh delay time (t rc min), ftb */
233*2b4ffbf6SChris Packham 		unsigned char byte_120;
234*2b4ffbf6SChris Packham 		unsigned char byte_121; /* fine offset for min row precharge delay time (t rp min), ftb */
235*2b4ffbf6SChris Packham 		unsigned char byte_122; /* fine offset for min ras to cas delay time (t rcd min), ftb */
236*2b4ffbf6SChris Packham 		unsigned char byte_123; /* fine offset for min cas latency time (t aa min), ftb */
237*2b4ffbf6SChris Packham 		unsigned char byte_124; /* fine offset for sdram max cycle time (t ck avg max), ftb */
238*2b4ffbf6SChris Packham 		unsigned char byte_125; /* fine offset for sdram min cycle time (t ck avg min), ftb */
239*2b4ffbf6SChris Packham 		unsigned char byte_126; /* crc for base configuration section, l-s-byte */
240*2b4ffbf6SChris Packham 		unsigned char byte_127; /* crc for base configuration section, m-s-byte */
241*2b4ffbf6SChris Packham 		/*
242*2b4ffbf6SChris Packham 		 * block 1: module specific parameters for unbuffered memory module types only
243*2b4ffbf6SChris Packham 		 */
244*2b4ffbf6SChris Packham 		union { /* (unbuffered) raw card extension, module nominal height */
245*2b4ffbf6SChris Packham 			unsigned char all_bits;
246*2b4ffbf6SChris Packham 			struct {
247*2b4ffbf6SChris Packham 				unsigned char nom_height_max:5, /* in mm */
248*2b4ffbf6SChris Packham 					raw_cad_ext:3;
249*2b4ffbf6SChris Packham 			} bit_fields;
250*2b4ffbf6SChris Packham 		} byte_128;
251*2b4ffbf6SChris Packham 		union { /* (unbuffered) module maximum thickness */
252*2b4ffbf6SChris Packham 			unsigned char all_bits;
253*2b4ffbf6SChris Packham 			struct {
254*2b4ffbf6SChris Packham 				unsigned char front_thickness_max:4, /* in mm */
255*2b4ffbf6SChris Packham 					back_thickness_max:4; /* in mm */
256*2b4ffbf6SChris Packham 			} bit_fields;
257*2b4ffbf6SChris Packham 		} byte_129;
258*2b4ffbf6SChris Packham 		union { /* (unbuffered) reference raw card used */
259*2b4ffbf6SChris Packham 			unsigned char all_bits;
260*2b4ffbf6SChris Packham 			struct {
261*2b4ffbf6SChris Packham 				unsigned char ref_raw_card:5,
262*2b4ffbf6SChris Packham 					ref_raw_card_rev:2,
263*2b4ffbf6SChris Packham 					ref_raw_card_ext:1;
264*2b4ffbf6SChris Packham 			} bit_fields;
265*2b4ffbf6SChris Packham 		} byte_130;
266*2b4ffbf6SChris Packham 		union { /* (unbuffered) address mapping from edge connector to dram */
267*2b4ffbf6SChris Packham 			unsigned char all_bits;
268*2b4ffbf6SChris Packham 			struct {
269*2b4ffbf6SChris Packham 				unsigned char rank_1_mapping:1,
270*2b4ffbf6SChris Packham 					reserved:7;
271*2b4ffbf6SChris Packham 			} bit_fields;
272*2b4ffbf6SChris Packham 		} byte_131;
273*2b4ffbf6SChris Packham 		unsigned char bytes_132_191[60]; /* reserved; all 0s */
274*2b4ffbf6SChris Packham 	} byte_fields;
275*2b4ffbf6SChris Packham };
276*2b4ffbf6SChris Packham 
277*2b4ffbf6SChris Packham int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[]);
278*2b4ffbf6SChris Packham enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data);
279*2b4ffbf6SChris Packham enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data);
280*2b4ffbf6SChris Packham unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data);
281*2b4ffbf6SChris Packham unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data);
282*2b4ffbf6SChris Packham unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data);
283*2b4ffbf6SChris Packham unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data);
284*2b4ffbf6SChris Packham int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data);
285*2b4ffbf6SChris Packham unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl);
286*2b4ffbf6SChris Packham enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data);
287*2b4ffbf6SChris Packham enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data);
288*2b4ffbf6SChris Packham 
289*2b4ffbf6SChris Packham #endif /* _MV_DDR_SPD_H */
290