]> git.sur5r.net Git - u-boot/blob - drivers/ddr/marvell/a38x/mv_ddr_spd.c
ARM: mvebu: a38x: sync ddr training code with upstream
[u-boot] / 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         /* FIXME: wa: set twr to a default value, if it's unset on spd */
85         if (timing_data[MV_DDR_TWR_MIN] == 0)
86                 timing_data[MV_DDR_TWR_MIN] = 15000;
87
88         /* t rcd min, ps */
89         calc_val = spd_data->byte_fields.byte_25 * MV_DDR_SPD_DATA_MTB +
90                 (signed char)spd_data->byte_fields.byte_122 * MV_DDR_SPD_DATA_FTB;
91         if (calc_val < 0)
92                 return 1;
93         timing_data[MV_DDR_TRCD_MIN] = calc_val;
94
95         /* t rp min, ps */
96         calc_val = spd_data->byte_fields.byte_26 * MV_DDR_SPD_DATA_MTB +
97                 (signed char)spd_data->byte_fields.byte_121 * MV_DDR_SPD_DATA_FTB;
98         if (calc_val < 0)
99                 return 1;
100         timing_data[MV_DDR_TRP_MIN] = calc_val;
101
102         /* t rc min, ps */
103         calc_val = (spd_data->byte_fields.byte_29 +
104                 (spd_data->byte_fields.byte_27.bit_fields.t_rc_min_msn << MV_DDR_SPD_MSB_OFFS)) *
105                 MV_DDR_SPD_DATA_MTB +
106                 (signed char)spd_data->byte_fields.byte_120 * MV_DDR_SPD_DATA_FTB;
107         if (calc_val < 0)
108                 return 1;
109         timing_data[MV_DDR_TRC_MIN] = calc_val;
110
111         /* t ras min, ps */
112         timing_data[MV_DDR_TRAS_MIN] = (spd_data->byte_fields.byte_28 +
113                 (spd_data->byte_fields.byte_27.bit_fields.t_ras_min_msn << MV_DDR_SPD_MSB_OFFS)) *
114                 MV_DDR_SPD_DATA_MTB;
115
116         /* t rrd s min, ps */
117         calc_val = spd_data->byte_fields.byte_38 * MV_DDR_SPD_DATA_MTB +
118                 (signed char)spd_data->byte_fields.byte_119 * MV_DDR_SPD_DATA_FTB;
119         if (calc_val < 0)
120                 return 1;
121         timing_data[MV_DDR_TRRD_S_MIN] = calc_val;
122
123         /* t rrd l min, ps */
124         calc_val = spd_data->byte_fields.byte_39 * MV_DDR_SPD_DATA_MTB +
125                 (signed char)spd_data->byte_fields.byte_118 * MV_DDR_SPD_DATA_FTB;
126         if (calc_val < 0)
127                 return 1;
128         timing_data[MV_DDR_TRRD_L_MIN] = calc_val;
129
130         /* t faw min, ps */
131         timing_data[MV_DDR_TFAW_MIN] = (spd_data->byte_fields.byte_37 +
132                 (spd_data->byte_fields.byte_36.bit_fields.t_faw_min_msn << MV_DDR_SPD_MSB_OFFS)) *
133                 MV_DDR_SPD_DATA_MTB;
134
135         /* t wtr s min, ps */
136         timing_data[MV_DDR_TWTR_S_MIN] = (spd_data->byte_fields.byte_44 +
137                 (spd_data->byte_fields.byte_43.bit_fields.t_wtr_s_min_msn << MV_DDR_SPD_MSB_OFFS)) *
138                 MV_DDR_SPD_DATA_MTB;
139         /* FIXME: wa: set twtr_s to a default value, if it's unset on spd */
140         if (timing_data[MV_DDR_TWTR_S_MIN] == 0)
141                 timing_data[MV_DDR_TWTR_S_MIN] = 2500;
142
143         /* t wtr l min, ps */
144         timing_data[MV_DDR_TWTR_L_MIN] = (spd_data->byte_fields.byte_45 +
145                 (spd_data->byte_fields.byte_43.bit_fields.t_wtr_l_min_msn << MV_DDR_SPD_MSB_OFFS)) *
146                 MV_DDR_SPD_DATA_MTB;
147         /* FIXME: wa: set twtr_l to a default value, if it's unset on spd */
148         if (timing_data[MV_DDR_TWTR_L_MIN] == 0)
149                 timing_data[MV_DDR_TWTR_L_MIN] = 7500;
150
151         return 0;
152 }
153
154 enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data)
155 {
156         unsigned char dev_width = spd_data->byte_fields.byte_12.bit_fields.device_width;
157         enum mv_ddr_dev_width ret_val;
158
159         switch (dev_width) {
160         case 0x00:
161                 ret_val = MV_DDR_DEV_WIDTH_4BIT;
162                 break;
163         case 0x01:
164                 ret_val = MV_DDR_DEV_WIDTH_8BIT;
165                 break;
166         case 0x02:
167                 ret_val = MV_DDR_DEV_WIDTH_16BIT;
168                 break;
169         case 0x03:
170                 ret_val = MV_DDR_DEV_WIDTH_32BIT;
171                 break;
172         default:
173                 ret_val = MV_DDR_DEV_WIDTH_LAST;
174         }
175
176         return ret_val;
177 }
178
179 enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data)
180 {
181         unsigned char die_cap = spd_data->byte_fields.byte_4.bit_fields.die_capacity;
182         enum mv_ddr_die_capacity ret_val;
183
184         switch (die_cap) {
185         case 0x00:
186                 ret_val = MV_DDR_DIE_CAP_256MBIT;
187                 break;
188         case 0x01:
189                 ret_val = MV_DDR_DIE_CAP_512MBIT;
190                 break;
191         case 0x02:
192                 ret_val = MV_DDR_DIE_CAP_1GBIT;
193                 break;
194         case 0x03:
195                 ret_val = MV_DDR_DIE_CAP_2GBIT;
196                 break;
197         case 0x04:
198                 ret_val = MV_DDR_DIE_CAP_4GBIT;
199                 break;
200         case 0x05:
201                 ret_val = MV_DDR_DIE_CAP_8GBIT;
202                 break;
203         case 0x06:
204                 ret_val = MV_DDR_DIE_CAP_16GBIT;
205                 break;
206         case 0x07:
207                 ret_val = MV_DDR_DIE_CAP_32GBIT;
208                 break;
209         case 0x08:
210                 ret_val = MV_DDR_DIE_CAP_12GBIT;
211                 break;
212         case 0x09:
213                 ret_val = MV_DDR_DIE_CAP_24GBIT;
214                 break;
215         default:
216                 ret_val = MV_DDR_DIE_CAP_LAST;
217         }
218
219         return ret_val;
220 }
221
222 unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data)
223 {
224         unsigned char mem_mirror = spd_data->byte_fields.byte_131.bit_fields.rank_1_mapping;
225
226         return mem_mirror;
227 }
228
229 enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data)
230 {
231         unsigned char pri_bus_width = spd_data->byte_fields.byte_13.bit_fields.primary_bus_width;
232         enum mv_ddr_pri_bus_width ret_val;
233
234         switch (pri_bus_width) {
235         case 0x00:
236                 ret_val = MV_DDR_PRI_BUS_WIDTH_8;
237                 break;
238         case 0x01:
239                 ret_val = MV_DDR_PRI_BUS_WIDTH_16;
240                 break;
241         case 0x02:
242                 ret_val = MV_DDR_PRI_BUS_WIDTH_32;
243                 break;
244         case 0x03:
245                 ret_val = MV_DDR_PRI_BUS_WIDTH_64;
246                 break;
247         default:
248                 ret_val = MV_DDR_PRI_BUS_WIDTH_LAST;
249         }
250
251         return ret_val;
252 }
253
254 enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data)
255 {
256         unsigned char bus_width_ext = spd_data->byte_fields.byte_13.bit_fields.bus_width_ext;
257         enum mv_ddr_bus_width_ext ret_val;
258
259         switch (bus_width_ext) {
260         case 0x00:
261                 ret_val = MV_DDR_BUS_WIDTH_EXT_0;
262                 break;
263         case 0x01:
264                 ret_val = MV_DDR_BUS_WIDTH_EXT_8;
265                 break;
266         default:
267                 ret_val = MV_DDR_BUS_WIDTH_EXT_LAST;
268         }
269
270         return ret_val;
271 }
272
273 static enum mv_ddr_pkg_rank mv_ddr_spd_pkg_rank_get(union mv_ddr_spd_data *spd_data)
274 {
275         unsigned char pkg_rank = spd_data->byte_fields.byte_12.bit_fields.dimm_pkg_ranks_num;
276         enum mv_ddr_pkg_rank ret_val;
277
278         switch (pkg_rank) {
279         case 0x00:
280                 ret_val = MV_DDR_PKG_RANK_1;
281                 break;
282         case 0x01:
283                 ret_val = MV_DDR_PKG_RANK_2;
284                 break;
285         case 0x02:
286                 ret_val = MV_DDR_PKG_RANK_3;
287                 break;
288         case 0x03:
289                 ret_val = MV_DDR_PKG_RANK_4;
290                 break;
291         case 0x04:
292                 ret_val = MV_DDR_PKG_RANK_5;
293                 break;
294         case 0x05:
295                 ret_val = MV_DDR_PKG_RANK_6;
296                 break;
297         case 0x06:
298                 ret_val = MV_DDR_PKG_RANK_7;
299                 break;
300         case 0x07:
301                 ret_val = MV_DDR_PKG_RANK_8;
302                 break;
303         default:
304                 ret_val = MV_DDR_PKG_RANK_LAST;
305         }
306
307         return ret_val;
308 }
309
310 static enum mv_ddr_die_count mv_ddr_spd_die_count_get(union mv_ddr_spd_data *spd_data)
311 {
312         unsigned char die_count = spd_data->byte_fields.byte_6.bit_fields.die_count;
313         enum mv_ddr_die_count ret_val;
314
315         switch (die_count) {
316         case 0x00:
317                 ret_val = MV_DDR_DIE_CNT_1;
318                 break;
319         case 0x01:
320                 ret_val = MV_DDR_DIE_CNT_2;
321                 break;
322         case 0x02:
323                 ret_val = MV_DDR_DIE_CNT_3;
324                 break;
325         case 0x03:
326                 ret_val = MV_DDR_DIE_CNT_4;
327                 break;
328         case 0x04:
329                 ret_val = MV_DDR_DIE_CNT_5;
330                 break;
331         case 0x05:
332                 ret_val = MV_DDR_DIE_CNT_6;
333                 break;
334         case 0x06:
335                 ret_val = MV_DDR_DIE_CNT_7;
336                 break;
337         case 0x07:
338                 ret_val = MV_DDR_DIE_CNT_8;
339                 break;
340         default:
341                 ret_val = MV_DDR_DIE_CNT_LAST;
342         }
343
344         return ret_val;
345 }
346
347 unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data)
348 {
349         unsigned char cs_bit_mask = 0x0;
350         enum mv_ddr_pkg_rank pkg_rank = mv_ddr_spd_pkg_rank_get(spd_data);
351         enum mv_ddr_die_count die_cnt = mv_ddr_spd_die_count_get(spd_data);
352
353         if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_1)
354                 cs_bit_mask = 0x1;
355         else if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_2)
356                 cs_bit_mask = 0x3;
357         else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_1)
358                 cs_bit_mask = 0x3;
359         else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_2)
360                 cs_bit_mask = 0xf;
361
362         return cs_bit_mask;
363 }
364
365 unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data)
366 {
367         unsigned char dev_type = spd_data->byte_fields.byte_2;
368
369         return dev_type;
370 }
371
372 unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data)
373 {
374         unsigned char module_type = spd_data->byte_fields.byte_3.bit_fields.module_type;
375
376         return module_type;
377 }