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