Home | History | Annotate | Download | only in a38x
      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 }
    378