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 } 376