Chris Packham | 1a07d21 | 2018-05-10 13:28:29 +1200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | /* |
| 3 | * Copyright (C) Marvell International Ltd. and its affiliates |
| 4 | */ |
| 5 | |
| 6 | #ifndef _MV_DDR_SPD_H |
| 7 | #define _MV_DDR_SPD_H |
| 8 | |
| 9 | #include "mv_ddr_topology.h" |
| 10 | |
| 11 | /* |
| 12 | * Based on JEDEC Standard No. 21-C, 4.1.2.L-4: |
| 13 | * Serial Presence Detect (SPD) for DDR4 SDRAM Modules |
| 14 | */ |
| 15 | |
| 16 | /* block 0: base configuration and dram parameters */ |
| 17 | #define MV_DDR_SPD_DATA_BLOCK0_SIZE 128 |
| 18 | /* block 1: module specific parameters sub-block */ |
| 19 | #define MV_DDR_SPD_DATA_BLOCK1M_SIZE 64 |
| 20 | /* block 1: hybrid memory parameters sub-block */ |
| 21 | #define MV_DDR_SPD_DATA_BLOCK1H_SIZE 64 |
| 22 | /* block 2: extended function parameter block */ |
| 23 | #define MV_DDR_SPD_DATA_BLOCK2E_SIZE 64 |
| 24 | /* block 2: manufacturing information */ |
| 25 | #define MV_DDR_SPD_DATA_BLOCK2M_SIZE 64 |
| 26 | /* block 3: end user programmable */ |
| 27 | #define MV_DDR_SPD_DATA_BLOCK3_SIZE 128 |
| 28 | |
| 29 | #define MV_DDR_SPD_DEV_TYPE_DDR4 0xc |
| 30 | #define MV_DDR_SPD_MODULE_TYPE_UDIMM 0x2 |
| 31 | #define MV_DDR_SPD_MODULE_TYPE_SO_DIMM 0x3 |
| 32 | #define MV_DDR_SPD_MODULE_TYPE_MINI_UDIMM 0x6 |
| 33 | #define MV_DDR_SPD_MODULE_TYPE_72BIT_SO_UDIMM 0x9 |
| 34 | #define MV_DDR_SPD_MODULE_TYPE_16BIT_SO_DIMM 0xc |
| 35 | #define MV_DDR_SPD_MODULE_TYPE_32BIT_SO_DIMM 0xd |
| 36 | |
| 37 | /* |
| 38 | * TODO: For now, the struct contains block 0 & block 1 with module specific |
| 39 | * parameters for unbuffered memory module types only. |
| 40 | */ |
| 41 | union mv_ddr_spd_data { |
| 42 | unsigned char all_bytes[MV_DDR_SPD_DATA_BLOCK0_SIZE + |
Sujeet Baranwal | 0d26759 | 2021-02-26 11:56:59 +0100 | [diff] [blame] | 43 | MV_DDR_SPD_DATA_BLOCK1M_SIZE + |
| 44 | MV_DDR_SPD_DATA_BLOCK1H_SIZE + |
| 45 | MV_DDR_SPD_DATA_BLOCK2E_SIZE + |
| 46 | MV_DDR_SPD_DATA_BLOCK2M_SIZE]; |
Chris Packham | 1a07d21 | 2018-05-10 13:28:29 +1200 | [diff] [blame] | 47 | struct { |
| 48 | /* block 0 */ |
| 49 | union { /* num of bytes used/num of bytes in spd device/crc coverage */ |
| 50 | unsigned char all_bits; |
| 51 | struct { |
| 52 | unsigned char spd_bytes_used:4, |
| 53 | spd_bytes_total:3, |
| 54 | reserved:1; |
| 55 | } bit_fields; |
| 56 | } byte_0; |
| 57 | union { /* spd revision */ |
| 58 | unsigned char all_bits; |
| 59 | struct { |
| 60 | unsigned char addtions_level:4, |
| 61 | encoding_level:4; |
| 62 | } bit_fields; |
| 63 | } byte_1; |
| 64 | unsigned char byte_2; /* key_byte/dram device type */ |
| 65 | union { /* key byte/module type */ |
| 66 | unsigned char all_bits; |
| 67 | struct { |
| 68 | unsigned char module_type:4, |
| 69 | hybrid_media:3, |
| 70 | hybrid:1; |
| 71 | } bit_fields; |
| 72 | } byte_3; |
| 73 | union { /* sdram density & banks */ |
| 74 | unsigned char all_bits; |
| 75 | struct { |
| 76 | unsigned char die_capacity:4, |
| 77 | bank_address:2, |
| 78 | bank_group:2; |
| 79 | } bit_fields; |
| 80 | } byte_4; |
| 81 | union { /* sdram addressing */ |
| 82 | unsigned char all_bits; |
| 83 | struct { |
| 84 | unsigned char col_address:3, |
| 85 | row_address:3, |
| 86 | reserved:2; |
| 87 | } bit_fields; |
| 88 | } byte_5; |
| 89 | union { /* sdram package type */ |
| 90 | unsigned char all_bits; |
| 91 | struct { |
| 92 | unsigned char signal_loading:2, |
| 93 | reserved:2, |
| 94 | die_count:3, |
| 95 | sdram_package_type:1; |
| 96 | } bit_fields; |
| 97 | } byte_6; |
| 98 | union { /* sdram optional features */ |
| 99 | unsigned char all_bits; |
| 100 | struct { |
| 101 | unsigned char mac:4, /* max activate count */ |
| 102 | t_maw:2, /* max activate window */ |
| 103 | reserved:2; /* all 0s */ |
| 104 | } bit_fields; |
| 105 | } byte_7; |
| 106 | unsigned char byte_8; /* sdram thermal & refresh options; reserved; 0x00 */ |
| 107 | union { /* other sdram optional features */ |
| 108 | unsigned char all_bits; |
| 109 | struct { |
| 110 | unsigned char reserved:5, /* all 0s */ |
| 111 | soft_ppr:1, |
| 112 | ppr:2; /* post package repair */ |
| 113 | } bit_fields; |
| 114 | } byte_9; |
| 115 | union { /* secondary sdram package type */ |
| 116 | unsigned char all_bits; |
| 117 | struct { |
| 118 | unsigned char signal_loading:2, |
| 119 | density_ratio:2, /* dram density ratio */ |
| 120 | die_count:3, |
| 121 | sdram_package_type:1; |
| 122 | } bit_fields; |
| 123 | } byte_10; |
| 124 | union { /* module nominal voltage, vdd */ |
| 125 | unsigned char all_bits; |
| 126 | struct { |
| 127 | unsigned char operable:1, |
| 128 | endurant:1, |
| 129 | reserved:5; /* all 0s */ |
| 130 | } bit_fields; |
| 131 | } byte_11; |
| 132 | union { /* module organization*/ |
| 133 | unsigned char all_bits; |
| 134 | struct { |
| 135 | unsigned char device_width:3, |
| 136 | dimm_pkg_ranks_num:3, /* package ranks per dimm number */ |
| 137 | rank_mix:1, |
| 138 | reserved:1; /* 0 */ |
| 139 | } bit_fields; |
| 140 | } byte_12; |
| 141 | union { /* module memory bus width */ |
| 142 | unsigned char all_bits; |
| 143 | struct { |
| 144 | unsigned char primary_bus_width:3, /* in bits */ |
| 145 | bus_width_ext:2, /* in bits */ |
| 146 | reserved:3; /* all 0s */ |
| 147 | } bit_fields; |
| 148 | } byte_13; |
| 149 | union { /* module thernal sensor */ |
| 150 | unsigned char all_bits; |
| 151 | struct { |
| 152 | unsigned char reserved:7, |
| 153 | thermal_sensor:1; |
| 154 | } bit_fields; |
| 155 | } byte_14; |
| 156 | union { /* extended module type */ |
| 157 | unsigned char all_bits; |
| 158 | struct { |
| 159 | unsigned char ext_base_module_type:4, |
| 160 | reserved:4; /* all 0s */ |
| 161 | } bit_fields; |
| 162 | } byte_15; |
| 163 | unsigned char byte_16; /* reserved; 0x00 */ |
| 164 | union { /* timebases */ |
| 165 | unsigned char all_bits; |
| 166 | struct { |
| 167 | unsigned char ftb:2, /* fine timebase */ |
| 168 | mtb:2, /* medium timebase */ |
| 169 | reserved:4; /* all 0s */ |
| 170 | } bit_fields; |
| 171 | } byte_17; |
| 172 | unsigned char byte_18; /* sdram min cycle time (t ck avg min), mtb */ |
| 173 | unsigned char byte_19; /* sdram max cycle time (t ck avg max), mtb */ |
| 174 | unsigned char byte_20; /* cas latencies supported, first byte */ |
| 175 | unsigned char byte_21; /* cas latencies supported, second byte */ |
| 176 | unsigned char byte_22; /* cas latencies supported, third byte */ |
| 177 | unsigned char byte_23; /* cas latencies supported, fourth byte */ |
| 178 | unsigned char byte_24; /* min cas latency time (t aa min), mtb */ |
| 179 | unsigned char byte_25; /* min ras to cas delay time (t rcd min), mtb */ |
| 180 | unsigned char byte_26; /* min row precharge delay time (t rp min), mtb */ |
| 181 | union { /* upper nibbles for t ras min & t rc min */ |
| 182 | unsigned char all_bits; |
| 183 | struct { |
| 184 | unsigned char t_ras_min_msn:4, /* t ras min most significant nibble */ |
| 185 | t_rc_min_msn:4; /* t rc min most significant nibble */ |
| 186 | } bit_fields; |
| 187 | } byte_27; |
| 188 | unsigned char byte_28; /* min active to precharge delay time (t ras min), l-s-byte, mtb */ |
| 189 | unsigned char byte_29; /* min active to active/refresh delay time (t rc min), l-s-byte, mtb */ |
| 190 | unsigned char byte_30; /* min refresh recovery delay time (t rfc1 min), l-s-byte, mtb */ |
| 191 | unsigned char byte_31; /* min refresh recovery delay time (t rfc1 min), m-s-byte, mtb */ |
| 192 | unsigned char byte_32; /* min refresh recovery delay time (t rfc2 min), l-s-byte, mtb */ |
| 193 | unsigned char byte_33; /* min refresh recovery delay time (t rfc2 min), m-s-byte, mtb */ |
| 194 | unsigned char byte_34; /* min refresh recovery delay time (t rfc4 min), l-s-byte, mtb */ |
| 195 | unsigned char byte_35; /* min refresh recovery delay time (t rfc4 min), m-s-byte, mtb */ |
| 196 | union { /* upper nibble for t faw */ |
| 197 | unsigned char all_bits; |
| 198 | struct { |
| 199 | unsigned char t_faw_min_msn:4, /* t faw min most significant nibble */ |
| 200 | reserved:4; |
| 201 | } bit_fields; |
| 202 | } byte_36; |
| 203 | unsigned char byte_37; /* min four activate window delay time (t faw min), l-s-byte, mtb */ |
| 204 | /* byte 38: min activate to activate delay time (t rrd_s min), diff bank group, mtb */ |
| 205 | unsigned char byte_38; |
| 206 | /* byte 39: min activate to activate delay time (t rrd_l min), same bank group, mtb */ |
| 207 | unsigned char byte_39; |
| 208 | unsigned char byte_40; /* min cas to cas delay time (t ccd_l min), same bank group, mtb */ |
| 209 | union { /* upper nibble for t wr min */ |
| 210 | unsigned char all_bits; |
| 211 | struct { |
| 212 | unsigned char t_wr_min_msn:4, /* t wr min most significant nibble */ |
| 213 | reserved:4; |
| 214 | } bit_fields; |
| 215 | } byte_41; |
| 216 | unsigned char byte_42; /* min write recovery time (t wr min) */ |
| 217 | union { /* upper nibbles for t wtr min */ |
| 218 | unsigned char all_bits; |
| 219 | struct { |
| 220 | unsigned char t_wtr_s_min_msn:4, /* t wtr s min most significant nibble */ |
| 221 | t_wtr_l_min_msn:4; /* t wtr l min most significant nibble */ |
| 222 | } bit_fields; |
| 223 | } byte_43; |
| 224 | unsigned char byte_44; /* min write to read time (t wtr s min), diff bank group, mtb */ |
| 225 | unsigned char byte_45; /* min write to read time (t wtr l min), same bank group, mtb */ |
| 226 | unsigned char bytes_46_59[14]; /* reserved; all 0s */ |
| 227 | unsigned char bytes_60_77[18]; /* TODO: connector to sdram bit mapping */ |
| 228 | unsigned char bytes_78_116[39]; /* reserved; all 0s */ |
| 229 | /* fine offset for min cas to cas delay time (t ccd_l min), same bank group, ftb */ |
| 230 | unsigned char byte_117; |
| 231 | /* fine offset for min activate to activate delay time (t rrd_l min), same bank group, ftb */ |
| 232 | unsigned char byte_118; |
| 233 | /* fine offset for min activate to activate delay time (t rrd_s min), diff bank group, ftb */ |
| 234 | unsigned char byte_119; |
| 235 | /* fine offset for min active to active/refresh delay time (t rc min), ftb */ |
| 236 | unsigned char byte_120; |
| 237 | unsigned char byte_121; /* fine offset for min row precharge delay time (t rp min), ftb */ |
| 238 | unsigned char byte_122; /* fine offset for min ras to cas delay time (t rcd min), ftb */ |
| 239 | unsigned char byte_123; /* fine offset for min cas latency time (t aa min), ftb */ |
| 240 | unsigned char byte_124; /* fine offset for sdram max cycle time (t ck avg max), ftb */ |
| 241 | unsigned char byte_125; /* fine offset for sdram min cycle time (t ck avg min), ftb */ |
| 242 | unsigned char byte_126; /* crc for base configuration section, l-s-byte */ |
| 243 | unsigned char byte_127; /* crc for base configuration section, m-s-byte */ |
| 244 | /* |
| 245 | * block 1: module specific parameters for unbuffered memory module types only |
| 246 | */ |
| 247 | union { /* (unbuffered) raw card extension, module nominal height */ |
| 248 | unsigned char all_bits; |
| 249 | struct { |
| 250 | unsigned char nom_height_max:5, /* in mm */ |
| 251 | raw_cad_ext:3; |
| 252 | } bit_fields; |
| 253 | } byte_128; |
| 254 | union { /* (unbuffered) module maximum thickness */ |
| 255 | unsigned char all_bits; |
| 256 | struct { |
| 257 | unsigned char front_thickness_max:4, /* in mm */ |
| 258 | back_thickness_max:4; /* in mm */ |
| 259 | } bit_fields; |
| 260 | } byte_129; |
| 261 | union { /* (unbuffered) reference raw card used */ |
| 262 | unsigned char all_bits; |
| 263 | struct { |
| 264 | unsigned char ref_raw_card:5, |
| 265 | ref_raw_card_rev:2, |
| 266 | ref_raw_card_ext:1; |
| 267 | } bit_fields; |
| 268 | } byte_130; |
| 269 | union { /* (unbuffered) address mapping from edge connector to dram */ |
| 270 | unsigned char all_bits; |
| 271 | struct { |
| 272 | unsigned char rank_1_mapping:1, |
| 273 | reserved:7; |
| 274 | } bit_fields; |
| 275 | } byte_131; |
| 276 | unsigned char bytes_132_191[60]; /* reserved; all 0s */ |
Sujeet Baranwal | 0d26759 | 2021-02-26 11:56:59 +0100 | [diff] [blame] | 277 | unsigned char bytes_192_255[MV_DDR_SPD_DATA_BLOCK1H_SIZE]; |
| 278 | unsigned char bytes_256_319[MV_DDR_SPD_DATA_BLOCK2E_SIZE]; |
| 279 | unsigned char bytes_320_383[MV_DDR_SPD_DATA_BLOCK2M_SIZE]; |
Chris Packham | 1a07d21 | 2018-05-10 13:28:29 +1200 | [diff] [blame] | 280 | } byte_fields; |
| 281 | }; |
| 282 | |
| 283 | int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[]); |
| 284 | enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data); |
| 285 | enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data); |
| 286 | unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data); |
| 287 | unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data); |
| 288 | unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data); |
| 289 | unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data); |
| 290 | int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data); |
| 291 | unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl); |
| 292 | enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data); |
| 293 | enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data); |
| 294 | |
| 295 | #endif /* _MV_DDR_SPD_H */ |