uboot/drivers/ddr/marvell/a38x/mv_ddr_spd.c
<<
>>
Prefs
   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