1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) Marvell International Ltd. and its affiliates
4 */
5
6#include "mv_ddr_spd.h"
7
8#define MV_DDR_SPD_DATA_MTB		125	/* medium timebase, ps */
9#define MV_DDR_SPD_DATA_FTB		1	/* fine timebase, ps */
10#define MV_DDR_SPD_MSB_OFFS		8	/* most significant byte offset, bits */
11
12#define MV_DDR_SPD_SUPPORTED_CLS_NUM	30
13
14static unsigned int mv_ddr_spd_supported_cls[MV_DDR_SPD_SUPPORTED_CLS_NUM];
15
16int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data)
17{
18	unsigned int byte, bit, start_cl;
19
20	start_cl = (spd_data->all_bytes[23] & 0x8) ? 23 : 7;
21
22	for (byte = 20; byte < 23; byte++) {
23		for (bit = 0; bit < 8; bit++) {
24			if (spd_data->all_bytes[byte] & (1 << bit))
25				mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit;
26			else
27				mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0;
28		}
29	}
30
31	for (byte = 23, bit = 0; bit < 6; bit++) {
32		if (spd_data->all_bytes[byte] & (1 << bit))
33			mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit;
34		else
35			mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0;
36	}
37
38	return 0;
39}
40
41unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl)
42{
43	unsigned int supported_cl;
44	int i = 0;
45
46	while (i < MV_DDR_SPD_SUPPORTED_CLS_NUM &&
47		mv_ddr_spd_supported_cls[i] < cl)
48		i++;
49
50	if (i < MV_DDR_SPD_SUPPORTED_CLS_NUM)
51		supported_cl = mv_ddr_spd_supported_cls[i];
52	else
53		supported_cl = 0;
54
55	return supported_cl;
56}
57
58int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[])
59{
60	int calc_val;
61
62	/* t ck avg min, ps */
63	calc_val = spd_data->byte_fields.byte_18 * MV_DDR_SPD_DATA_MTB +
64		(signed char)spd_data->byte_fields.byte_125 * MV_DDR_SPD_DATA_FTB;
65	if (calc_val < 0)
66		return 1;
67	timing_data[MV_DDR_TCK_AVG_MIN] = calc_val;
68
69	/* t aa min, ps */
70	calc_val = spd_data->byte_fields.byte_24 * MV_DDR_SPD_DATA_MTB +
71		(signed char)spd_data->byte_fields.byte_123 * MV_DDR_SPD_DATA_FTB;
72	if (calc_val < 0)
73		return 1;
74	timing_data[MV_DDR_TAA_MIN] = calc_val;
75
76	/* t rfc1 min, ps */
77	timing_data[MV_DDR_TRFC1_MIN] = (spd_data->byte_fields.byte_30 +
78		(spd_data->byte_fields.byte_31 << MV_DDR_SPD_MSB_OFFS)) * MV_DDR_SPD_DATA_MTB;
79
80	/* t wr min, ps */
81	timing_data[MV_DDR_TWR_MIN] = (spd_data->byte_fields.byte_42 +
82		(spd_data->byte_fields.byte_41.bit_fields.t_wr_min_msn << MV_DDR_SPD_MSB_OFFS)) *
83		MV_DDR_SPD_DATA_MTB;
84
85	/* t rcd min, ps */
86	calc_val = spd_data->byte_fields.byte_25 * MV_DDR_SPD_DATA_MTB +
87		(signed char)spd_data->byte_fields.byte_122 * MV_DDR_SPD_DATA_FTB;
88	if (calc_val < 0)
89		return 1;
90	timing_data[MV_DDR_TRCD_MIN] = calc_val;
91
92	/* t rp min, ps */
93	calc_val = spd_data->byte_fields.byte_26 * MV_DDR_SPD_DATA_MTB +
94		(signed char)spd_data->byte_fields.byte_121 * MV_DDR_SPD_DATA_FTB;
95	if (calc_val < 0)
96		return 1;
97	timing_data[MV_DDR_TRP_MIN] = calc_val;
98
99	/* t rc min, ps */
100	calc_val = (spd_data->byte_fields.byte_29 +
101		(spd_data->byte_fields.byte_27.bit_fields.t_rc_min_msn << MV_DDR_SPD_MSB_OFFS)) *
102		MV_DDR_SPD_DATA_MTB +
103		(signed char)spd_data->byte_fields.byte_120 * MV_DDR_SPD_DATA_FTB;
104	if (calc_val < 0)
105		return 1;
106	timing_data[MV_DDR_TRC_MIN] = calc_val;
107
108	/* t ras min, ps */
109	timing_data[MV_DDR_TRAS_MIN] = (spd_data->byte_fields.byte_28 +
110		(spd_data->byte_fields.byte_27.bit_fields.t_ras_min_msn << MV_DDR_SPD_MSB_OFFS)) *
111		MV_DDR_SPD_DATA_MTB;
112
113	/* t rrd s min, ps */
114	calc_val = spd_data->byte_fields.byte_38 * MV_DDR_SPD_DATA_MTB +
115		(signed char)spd_data->byte_fields.byte_119 * MV_DDR_SPD_DATA_FTB;
116	if (calc_val < 0)
117		return 1;
118	timing_data[MV_DDR_TRRD_S_MIN] = calc_val;
119
120	/* t rrd l min, ps */
121	calc_val = spd_data->byte_fields.byte_39 * MV_DDR_SPD_DATA_MTB +
122		(signed char)spd_data->byte_fields.byte_118 * MV_DDR_SPD_DATA_FTB;
123	if (calc_val < 0)
124		return 1;
125	timing_data[MV_DDR_TRRD_L_MIN] = calc_val;
126
127	/* t ccd l min, ps */
128	calc_val = spd_data->byte_fields.byte_40 * MV_DDR_SPD_DATA_MTB +
129		(signed char)spd_data->byte_fields.byte_117 * MV_DDR_SPD_DATA_FTB;
130	if (calc_val < 0)
131		return 1;
132	timing_data[MV_DDR_TCCD_L_MIN] = calc_val;
133
134	/* t faw min, ps */
135	timing_data[MV_DDR_TFAW_MIN] = (spd_data->byte_fields.byte_37 +
136		(spd_data->byte_fields.byte_36.bit_fields.t_faw_min_msn << MV_DDR_SPD_MSB_OFFS)) *
137		MV_DDR_SPD_DATA_MTB;
138
139	/* t wtr s min, ps */
140	timing_data[MV_DDR_TWTR_S_MIN] = (spd_data->byte_fields.byte_44 +
141		(spd_data->byte_fields.byte_43.bit_fields.t_wtr_s_min_msn << MV_DDR_SPD_MSB_OFFS)) *
142		MV_DDR_SPD_DATA_MTB;
143
144	/* t wtr l min, ps */
145	timing_data[MV_DDR_TWTR_L_MIN] = (spd_data->byte_fields.byte_45 +
146		(spd_data->byte_fields.byte_43.bit_fields.t_wtr_l_min_msn << MV_DDR_SPD_MSB_OFFS)) *
147		MV_DDR_SPD_DATA_MTB;
148
149	return 0;
150}
151
152enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data)
153{
154	unsigned char dev_width = spd_data->byte_fields.byte_12.bit_fields.device_width;
155	enum mv_ddr_dev_width ret_val;
156
157	switch (dev_width) {
158	case 0x00:
159		ret_val = MV_DDR_DEV_WIDTH_4BIT;
160		break;
161	case 0x01:
162		ret_val = MV_DDR_DEV_WIDTH_8BIT;
163		break;
164	case 0x02:
165		ret_val = MV_DDR_DEV_WIDTH_16BIT;
166		break;
167	case 0x03:
168		ret_val = MV_DDR_DEV_WIDTH_32BIT;
169		break;
170	default:
171		ret_val = MV_DDR_DEV_WIDTH_LAST;
172	}
173
174	return ret_val;
175}
176
177enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data)
178{
179	unsigned char die_cap = spd_data->byte_fields.byte_4.bit_fields.die_capacity;
180	enum mv_ddr_die_capacity ret_val;
181
182	switch (die_cap) {
183	case 0x00:
184		ret_val = MV_DDR_DIE_CAP_256MBIT;
185		break;
186	case 0x01:
187		ret_val = MV_DDR_DIE_CAP_512MBIT;
188		break;
189	case 0x02:
190		ret_val = MV_DDR_DIE_CAP_1GBIT;
191		break;
192	case 0x03:
193		ret_val = MV_DDR_DIE_CAP_2GBIT;
194		break;
195	case 0x04:
196		ret_val = MV_DDR_DIE_CAP_4GBIT;
197		break;
198	case 0x05:
199		ret_val = MV_DDR_DIE_CAP_8GBIT;
200		break;
201	case 0x06:
202		ret_val = MV_DDR_DIE_CAP_16GBIT;
203		break;
204	case 0x07:
205		ret_val = MV_DDR_DIE_CAP_32GBIT;
206		break;
207	case 0x08:
208		ret_val = MV_DDR_DIE_CAP_12GBIT;
209		break;
210	case 0x09:
211		ret_val = MV_DDR_DIE_CAP_24GBIT;
212		break;
213	default:
214		ret_val = MV_DDR_DIE_CAP_LAST;
215	}
216
217	return ret_val;
218}
219
220unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data)
221{
222	unsigned char mem_mirror = spd_data->byte_fields.byte_131.bit_fields.rank_1_mapping;
223
224	return mem_mirror;
225}
226
227enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data)
228{
229	unsigned char pri_bus_width = spd_data->byte_fields.byte_13.bit_fields.primary_bus_width;
230	enum mv_ddr_pri_bus_width ret_val;
231
232	switch (pri_bus_width) {
233	case 0x00:
234		ret_val = MV_DDR_PRI_BUS_WIDTH_8;
235		break;
236	case 0x01:
237		ret_val = MV_DDR_PRI_BUS_WIDTH_16;
238		break;
239	case 0x02:
240		ret_val = MV_DDR_PRI_BUS_WIDTH_32;
241		break;
242	case 0x03:
243		ret_val = MV_DDR_PRI_BUS_WIDTH_64;
244		break;
245	default:
246		ret_val = MV_DDR_PRI_BUS_WIDTH_LAST;
247	}
248
249	return ret_val;
250}
251
252enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data)
253{
254	unsigned char bus_width_ext = spd_data->byte_fields.byte_13.bit_fields.bus_width_ext;
255	enum mv_ddr_bus_width_ext ret_val;
256
257	switch (bus_width_ext) {
258	case 0x00:
259		ret_val = MV_DDR_BUS_WIDTH_EXT_0;
260		break;
261	case 0x01:
262		ret_val = MV_DDR_BUS_WIDTH_EXT_8;
263		break;
264	default:
265		ret_val = MV_DDR_BUS_WIDTH_EXT_LAST;
266	}
267
268	return ret_val;
269}
270
271static enum mv_ddr_pkg_rank mv_ddr_spd_pkg_rank_get(union mv_ddr_spd_data *spd_data)
272{
273	unsigned char pkg_rank = spd_data->byte_fields.byte_12.bit_fields.dimm_pkg_ranks_num;
274	enum mv_ddr_pkg_rank ret_val;
275
276	switch (pkg_rank) {
277	case 0x00:
278		ret_val = MV_DDR_PKG_RANK_1;
279		break;
280	case 0x01:
281		ret_val = MV_DDR_PKG_RANK_2;
282		break;
283	case 0x02:
284		ret_val = MV_DDR_PKG_RANK_3;
285		break;
286	case 0x03:
287		ret_val = MV_DDR_PKG_RANK_4;
288		break;
289	case 0x04:
290		ret_val = MV_DDR_PKG_RANK_5;
291		break;
292	case 0x05:
293		ret_val = MV_DDR_PKG_RANK_6;
294		break;
295	case 0x06:
296		ret_val = MV_DDR_PKG_RANK_7;
297		break;
298	case 0x07:
299		ret_val = MV_DDR_PKG_RANK_8;
300		break;
301	default:
302		ret_val = MV_DDR_PKG_RANK_LAST;
303	}
304
305	return ret_val;
306}
307
308static enum mv_ddr_die_count mv_ddr_spd_die_count_get(union mv_ddr_spd_data *spd_data)
309{
310	unsigned char die_count = spd_data->byte_fields.byte_6.bit_fields.die_count;
311	enum mv_ddr_die_count ret_val;
312
313	switch (die_count) {
314	case 0x00:
315		ret_val = MV_DDR_DIE_CNT_1;
316		break;
317	case 0x01:
318		ret_val = MV_DDR_DIE_CNT_2;
319		break;
320	case 0x02:
321		ret_val = MV_DDR_DIE_CNT_3;
322		break;
323	case 0x03:
324		ret_val = MV_DDR_DIE_CNT_4;
325		break;
326	case 0x04:
327		ret_val = MV_DDR_DIE_CNT_5;
328		break;
329	case 0x05:
330		ret_val = MV_DDR_DIE_CNT_6;
331		break;
332	case 0x06:
333		ret_val = MV_DDR_DIE_CNT_7;
334		break;
335	case 0x07:
336		ret_val = MV_DDR_DIE_CNT_8;
337		break;
338	default:
339		ret_val = MV_DDR_DIE_CNT_LAST;
340	}
341
342	return ret_val;
343}
344
345unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data)
346{
347	unsigned char cs_bit_mask = 0x0;
348	enum mv_ddr_pkg_rank pkg_rank = mv_ddr_spd_pkg_rank_get(spd_data);
349	enum mv_ddr_die_count die_cnt = mv_ddr_spd_die_count_get(spd_data);
350
351	if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_1)
352		cs_bit_mask = 0x1;
353	else if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_2)
354		cs_bit_mask = 0x3;
355	else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_1)
356		cs_bit_mask = 0x3;
357	else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_2)
358		cs_bit_mask = 0xf;
359
360	return cs_bit_mask;
361}
362
363unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data)
364{
365	unsigned char dev_type = spd_data->byte_fields.byte_2;
366
367	return dev_type;
368}
369
370unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data)
371{
372	unsigned char module_type = spd_data->byte_fields.byte_3.bit_fields.module_type;
373
374	return module_type;
375}
376