Merge branch '2020-05-18-reduce-size-of-common.h'
[oweals/u-boot.git] / drivers / ddr / marvell / a38x / mv_ddr_spd.c
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
14 static unsigned int mv_ddr_spd_supported_cls[MV_DDR_SPD_SUPPORTED_CLS_NUM];
15
16 int 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
41 unsigned 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
58 int 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
152 enum 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
177 enum 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
220 unsigned 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
227 enum 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
252 enum 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
271 static 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
308 static 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
345 unsigned 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
363 unsigned 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
370 unsigned 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 }