diff options
Diffstat (limited to 'src/usr/hwpf/hwp/dram_training/mss_lrdimm_funcs/mss_lrdimm_funcs.C')
-rw-r--r-- | src/usr/hwpf/hwp/dram_training/mss_lrdimm_funcs/mss_lrdimm_funcs.C | 1965 |
1 files changed, 1965 insertions, 0 deletions
diff --git a/src/usr/hwpf/hwp/dram_training/mss_lrdimm_funcs/mss_lrdimm_funcs.C b/src/usr/hwpf/hwp/dram_training/mss_lrdimm_funcs/mss_lrdimm_funcs.C new file mode 100644 index 000000000..57bdab249 --- /dev/null +++ b/src/usr/hwpf/hwp/dram_training/mss_lrdimm_funcs/mss_lrdimm_funcs.C @@ -0,0 +1,1965 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/hwp/dram_training/mss_lrdimm_funcs/mss_lrdimm_funcs.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +// $Id: mss_lrdimm_funcs.C,v 1.4 2013/09/16 13:56:38 bellows Exp $ +//------------------------------------------------------------------------------ +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//------------------------------------------------------------------------------ +// *! TITLE : mss_lrdimm_funcs.C +// *! DESCRIPTION : Tools for LRDIMM centaur procedures +// *! OWNER NAME : kcook@us.ibm.com +// *! BACKUP NAME : mwuu@us.ibm.com +// #! ADDITIONAL COMMENTS : +// + +//------------------------------------------------------------------------------ +// Don't forget to create CVS comments when you check in your changes! +//------------------------------------------------------------------------------ +// CHANGE HISTORY: +//------------------------------------------------------------------------------ +// Version:| Author: | Date: | Comment: +//---------|----------|---------|----------------------------------------------- +// 1.4 | 09/16/13 | bellows | Hostboot compile update +// 1.3 | 09/16/13 | bellows | Added ID tag. +// 1.2 | 09/13/13 | kcook | Updated define FAPI_LRDIMM token. +// 1.1 | 08/27/13 | kcook | First drop of Centaur + +//---------------------------------------------------------------------- +// Includes +//---------------------------------------------------------------------- + +#include <fapi.H> +#include <mss_lrdimm_funcs.H> +#include <mss_funcs.H> + +#ifdef FAPI_LRDIMM +const uint8_t MAX_NUM_DIMMS = 2; +const uint8_t MAX_NUM_LR_RANKS = 8; +const uint8_t MRS1_BA = 1; +const uint8_t PORT_SIZE = 2; +const uint8_t DIMM_SIZE = 2; +const uint8_t RANK_SIZE = 4; +const uint32_t MSS_EFF_VALID = 255; + + +using namespace fapi; + +fapi::ReturnCode mss_lrdimm_rcd_load( Target& i_target, uint32_t port_number, uint32_t& ccs_inst_cnt) +{ + ReturnCode rc; + uint8_t num_drops_per_port; + // LRDIMM + uint8_t func1_rcd_number_array_u8[12] = {7,0,1,2,8,9,10,11,12,13,14,15}; + uint8_t func2_rcd_number_array_u8[8] = {7,0,1,2,3,4,5,6}; + uint8_t func3_rcd_number_array_u8[7] = {7,0,1,2,6,8,9}; + uint8_t funcODT_rcd_number_array_u8[3] = {7,10,11}; + uint8_t *p_func_num_arr; + ecmdDataBufferBase data_buff_rcd_word(64); + uint64_t func_rcd_control_word[2]; + uint8_t num_ranks_array[2][2]; //[port][dimm] + uint8_t dimm_number; + uint8_t rank_number; + uint64_t spd_func_words; + uint64_t att_spd_func_words[2][2]; + uint8_t num_rows; + uint8_t num_cols; + uint8_t dram_width; + uint64_t l_func1_mask = 0x00000000F00FFFFFLL; + uint8_t l_rcd_cntl_word_0; + uint8_t l_rcd_cntl_word_1; + uint8_t l_rcd_cntl_word_2; + uint8_t l_rcd_cntl_word_3; + uint8_t l_rcd_cntl_word_4; + uint8_t l_rcd_cntl_word_5; + uint8_t l_rcd_cntl_word_6; + uint8_t l_rcd_cntl_word_7; + uint8_t l_rcd_cntl_word_8; + uint8_t l_rcd_cntl_word_9; + uint8_t l_rcd_cntl_word_10; + uint8_t l_rcd_cntl_word_11; + uint8_t dimm_func_vec; + + rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target, num_ranks_array); + if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_LRDIMM_ADDITIONAL_CNTL_WORDS, &i_target, att_spd_func_words); + if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_ROWS, &i_target, num_rows); + if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_COLS, &i_target, num_cols); + if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target, dram_width); + if (rc) return rc; + rc=FAPI_ATTR_GET(ATTR_MSS_EFF_DIMM_FUNCTIONAL_VECTOR, &i_target, dimm_func_vec); + if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_NUM_DROPS_PER_PORT, &i_target, num_drops_per_port); + if(rc) return rc; + + + // Fucntion 1 + for (dimm_number = 0;dimm_number < MAX_NUM_DIMMS; dimm_number++) + { + + if ( num_ranks_array[port_number][dimm_number] != 0 ) + { + //F[1]RC0 IBT settings for DCS pins + l_rcd_cntl_word_0 = 0; // IBT DCS[1:0] 100 Ohm, DCS[3:2] IBT as defined DCS[1:0] + l_rcd_cntl_word_1 = 0; //IBT DCKE 100 Ohm + l_rcd_cntl_word_2 = 0; //IBT DODT[1:0] 100 Ohm + + l_rcd_cntl_word_7 = 1; //Function select + l_rcd_cntl_word_9 = 0; //Refresh stagger = 0clocks + l_rcd_cntl_word_10 = 0; //Refresh stagger limit = unimited + + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_0, 0,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_1, 4,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_2, 8,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_7, 28,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_9, 36,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_10, 40,4); + + func_rcd_control_word[dimm_number] = data_buff_rcd_word.getDoubleWord(0); + if(rc) return rc; + spd_func_words = att_spd_func_words[port_number][dimm_number] & l_func1_mask; // SPD for F[1]RC8,11-15 + func_rcd_control_word[dimm_number] = func_rcd_control_word[dimm_number] | spd_func_words; + } + } + + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + p_func_num_arr = func1_rcd_number_array_u8; + rc = mss_spec_rcd_load(i_target, port_number, p_func_num_arr, + sizeof(func1_rcd_number_array_u8)/sizeof(func1_rcd_number_array_u8[0]), + func_rcd_control_word , ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + // Function 2 + for (dimm_number = 0;dimm_number < MAX_NUM_DIMMS; dimm_number++) + { + if ( num_ranks_array[port_number][dimm_number] != 0 ) + { + l_rcd_cntl_word_0 = 0; // Transparent mode + l_rcd_cntl_word_1 = 0; // Reset control + l_rcd_cntl_word_2 = 0; // SMBus access control + l_rcd_cntl_word_3 = 8; // Training control & Errorout enable driven Low when Training + l_rcd_cntl_word_4 = 0; // MEMBIST Rank control + + //RC5 DRAM row & column addressing + if ( num_rows == 13 ) + { + if ( num_cols == 10 ) + { + l_rcd_cntl_word_5 = 0; + } + else if ( num_cols == 11 ) + { + l_rcd_cntl_word_5 = 1; + } + else if ( num_cols == 12 ) + { + l_rcd_cntl_word_5 = 2; + } + else if ( num_cols == 3 ) + { + l_rcd_cntl_word_5 = 3; + } + } + else if ( num_rows == 14 ) + { + if ( num_cols == 10 ) + { + l_rcd_cntl_word_5 = 4; + } + else if ( num_cols == 11 ) + { + l_rcd_cntl_word_5 = 5; + } + else if ( num_cols == 12 ) + { + l_rcd_cntl_word_5 = 6; + } + else if ( num_cols == 3 ) + { + l_rcd_cntl_word_5 = 7; + } + } + else if ( num_rows == 15 ) + { + if ( num_cols == 10 ) + { + l_rcd_cntl_word_5 = 8; + } + else if ( num_cols == 11 ) + { + l_rcd_cntl_word_5 = 9; + } + else if ( num_cols == 12 ) + { + l_rcd_cntl_word_5 = 10; + } + else if ( num_cols == 3 ) + { + l_rcd_cntl_word_5 = 11; + } + } + else if ( num_rows == 16 ) + { + if ( num_cols == 10 ) + { + l_rcd_cntl_word_5 = 12; + } + else if ( num_cols == 11 ) + { + l_rcd_cntl_word_5 = 13; + } + else if ( num_cols == 12 ) + { + l_rcd_cntl_word_5 = 14; + } + else if ( num_cols == 3 ) + { + l_rcd_cntl_word_5 = 15; + } + } + + l_rcd_cntl_word_6 = 0; // MEMBIST control + l_rcd_cntl_word_7 = 2; //Function select + + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_0, 0,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_1, 4,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_2, 8,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_3,12,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_4,16,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_5,20,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_6,24,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_7, 28,4); + + func_rcd_control_word[dimm_number] = data_buff_rcd_word.getDoubleWord(0); + if(rc) return rc; + } + } + + + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + p_func_num_arr = func2_rcd_number_array_u8; + rc = mss_spec_rcd_load(i_target, port_number, p_func_num_arr, + sizeof(func2_rcd_number_array_u8)/sizeof(func2_rcd_number_array_u8[0]), + func_rcd_control_word , ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + // Function 3 + for (dimm_number = 0;dimm_number < MAX_NUM_DIMMS; dimm_number++) + { + if ( num_ranks_array[port_number][dimm_number] != 0 ) + { + data_buff_rcd_word.setDoubleWord(0, att_spd_func_words[port_number][dimm_number]); + data_buff_rcd_word.extractToRight(&l_rcd_cntl_word_8 , 40, 4); // f[3]RC8 is in space RCD10 + data_buff_rcd_word.extractToRight(&l_rcd_cntl_word_9 , 36, 4); + + //F[3]RC0 connector interface DQ RTT_Nom Termination, TDQS control + if ( num_drops_per_port == ENUM_ATTR_EFF_NUM_DROPS_PER_PORT_DUAL ) + { // Single rank, dual drop + if ( dram_width == 8 ) + { + l_rcd_cntl_word_0 = 9; // RTT_Nom 60 Ohm, TDQS enabled + } + else + { + l_rcd_cntl_word_0 = 1; // RTT_NOM 60 Ohm, TDQS disabled + } + } + else + { // Single rank, Single drop + if ( dram_width == 8 ) + { + l_rcd_cntl_word_0 = 9; // RTT_Nom 60 Ohm, TDQS enabled + } + else + { + l_rcd_cntl_word_0 = 1; // RTT_NOM 60 Ohm, TDQS disabled + } + } + + //F[3]RC1 connector interface DQ RTT_WR termination & Reference voltage + if ( num_drops_per_port == ENUM_ATTR_EFF_NUM_DROPS_PER_PORT_DUAL ) + { // Single rank, dual drop + l_rcd_cntl_word_1 = 2; // RTT_WR 120 Ohm , VrefDQ input pin + l_rcd_cntl_word_2 = 1; // Connecter interface DQ/DQS output driver imp 34 Ohm, DQ/DQS drivers enabled + } + else + { // Single rank, Single drop + l_rcd_cntl_word_1 = 0; // RTT_WR disabled, VrefDQ input pin + l_rcd_cntl_word_2 = 1; // Connecter interface DQ/DQS output driver imp 34 Ohm, DQ/DQS drivers enabled + } + + FAPI_INF("Using ATTR_EFF_SCHMOO_TEST_VALID for dq LRDIMM timing mode"); + rc=FAPI_ATTR_GET(ATTR_EFF_SCHMOO_TEST_VALID, &i_target, l_rcd_cntl_word_6); + + l_rcd_cntl_word_7 = 3; //Function select + + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_0, 0,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_1, 4,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_2, 8,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_6,24,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_7, 28,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_8,32,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_9, 36,4); + + func_rcd_control_word[dimm_number] = data_buff_rcd_word.getDoubleWord(0); + if(rc) return rc; + } + } + + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + p_func_num_arr = func3_rcd_number_array_u8; + rc = mss_spec_rcd_load(i_target, port_number, p_func_num_arr, + sizeof(func3_rcd_number_array_u8)/sizeof(func3_rcd_number_array_u8[0]), + func_rcd_control_word , ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + for ( rank_number = 0; rank_number < MAX_NUM_LR_RANKS; rank_number++ ) + { + for (dimm_number = 0;dimm_number < MAX_NUM_DIMMS; dimm_number++) + { + if ( num_ranks_array[port_number][dimm_number] != 0 ) + { + data_buff_rcd_word.setDoubleWord(0, att_spd_func_words[port_number][dimm_number]); + data_buff_rcd_word.extractToRight(&l_rcd_cntl_word_10 , rank_number/2*8, 4); // RC10 is in space RCD0/2/4/6 + data_buff_rcd_word.extractToRight(&l_rcd_cntl_word_11 , rank_number/2*8+4, 4); // RC11 is in space RCD1/3/5/7 + + l_rcd_cntl_word_7 = rank_number + 3; // Function word select 3:10 for Ranks 0-7 + + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_7, 28,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_10,40,4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_11,44,4); + + func_rcd_control_word[dimm_number] = data_buff_rcd_word.getDoubleWord(0); + if(rc) return rc; + } + } + + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + p_func_num_arr = funcODT_rcd_number_array_u8; + rc = mss_spec_rcd_load(i_target, port_number, p_func_num_arr, + sizeof(funcODT_rcd_number_array_u8)/sizeof(funcODT_rcd_number_array_u8[0]), + func_rcd_control_word , ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + } // end rank loop + + // Function 13 + l_rcd_cntl_word_7 = 13; + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + + uint8_t Rx_MR1_2_DATA[2][2]; + rc=FAPI_ATTR_GET(ATTR_LRDIMM_MR12_REG, &i_target, Rx_MR1_2_DATA); + if(rc) return rc; + + uint8_t rcw = 7; + uint64_t rcd0_15[2] = { 0x0000000D00000000ll, // select FN 13 dimm0 + 0x0000000D00000000ll }; // " dimm1 + + // set FN 13 via RC 7 + rc = mss_spec_rcd_load( i_target, port_number, &rcw, 1, rcd0_15, ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", + uint32_t(rc), rc.getCreator()); + return rc; + } + + uint8_t func13_rcd_number_array_size = 4; + uint8_t func13_rcd_number_array_u8[4] = { 10, 11, 14, 15 }; + p_func_num_arr = func13_rcd_number_array_u8; + + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_7, 28,4); // select F13 + + const uint8_t num_ecw = 11; // number of external funcs + uint8_t R2_7_MR1_2_DATA[2][2]; + R2_7_MR1_2_DATA[port_number][0] = Rx_MR1_2_DATA[port_number][0] & 0xE3; // disable RTT_NOM on ranks 2:7 + R2_7_MR1_2_DATA[port_number][1] = Rx_MR1_2_DATA[port_number][1] & 0xE3; // disable RTT_NOM on ranks 2:7 + + + // extended control word addr, data + uint8_t ext_funcs[MAX_NUM_DIMMS][num_ecw][2] = { + { + {0xAC, 0x00}, // MRS_CTRL = 0xAC; snoop/forward/store + // MRx_SNOOP = 0xC8-CF MR(0:3) MR to DRAM 0xC8/C9-CE/CF + {0xC8, 0x00}, // MR0_SNOOP(0:7) = 0xC8 MR0 to DRAM + {0xC9, 0x00}, // MR0_SNOOP(8:15) = 0xC9; MR0 to DRAM + // Rx_MR1_2 = 0xB8-BF; R(0:7) ranks, RTT_WR, RTT_NOM, D_IMP + {0xB8, Rx_MR1_2_DATA[port_number][0]}, // rank 0 + {0xB9, Rx_MR1_2_DATA[port_number][0]}, // rank 1 + {0xBA, R2_7_MR1_2_DATA[port_number][0]}, // rank 2 + {0xBB, R2_7_MR1_2_DATA[port_number][0]}, // rank 3 + {0xBC, R2_7_MR1_2_DATA[port_number][0]}, // rank 4 + {0xBD, R2_7_MR1_2_DATA[port_number][0]}, // rank 5 + {0xBE, R2_7_MR1_2_DATA[port_number][0]}, // rank 6 + {0xBF, R2_7_MR1_2_DATA[port_number][0]} // rank 7 + }, + { + {0xAC, 0x00}, // MRS_CTRL = 0xAC; snoop/forward/store + // MRx_SNOOP = 0xC8-CF MR(0:3) MR to DRAM 0xC8/C9-CE/CF + {0xC8, 0x00}, // MR0_SNOOP(0:7) = 0xC8 MR0 to DRAM + {0xC9, 0x00}, // MR0_SNOOP(8:15) = 0xC9; MR0 to DRAM + // Rx_MR1_2 = 0xB8-BF; R(0:7) ranks, RTT_WR, RTT_NOM, D_IMP + {0xB8, Rx_MR1_2_DATA[port_number][1]}, // rank 0 + {0xB9, Rx_MR1_2_DATA[port_number][1]}, // rank 1 + {0xBA, R2_7_MR1_2_DATA[port_number][1]}, // rank 2 + {0xBB, R2_7_MR1_2_DATA[port_number][1]}, // rank 3 + {0xBC, R2_7_MR1_2_DATA[port_number][1]}, // rank 4 + {0xBD, R2_7_MR1_2_DATA[port_number][1]}, // rank 5 + {0xBE, R2_7_MR1_2_DATA[port_number][1]}, // rank 6 + {0xBF, R2_7_MR1_2_DATA[port_number][1]} // rank 7 + } + }; + for (uint8_t i=0; i < num_ecw; i++) + { + // set func_rcd_control_word[dimm_number] + for (dimm_number = 0;dimm_number < MAX_NUM_DIMMS; dimm_number++) + { + if ( num_ranks_array[port_number][dimm_number] != 0 ) + { + // load address + data_buff_rcd_word.insertFromRight(ext_funcs[dimm_number][i][0],40,4); // lsb address + data_buff_rcd_word.insert(ext_funcs[dimm_number][i][0],44,4); // msb address + // load data + data_buff_rcd_word.insertFromRight(ext_funcs[dimm_number][i][1], 56,4); // lsb data + data_buff_rcd_word.insert(ext_funcs[dimm_number][i][1], 60,4); // msb data + + func_rcd_control_word[dimm_number] = data_buff_rcd_word.getDoubleWord(0); + if(rc) return rc; + } // end if has ranks + } // end dimm loop + + + // load CCS with F13 RC 10:11, 14:15 + rc = mss_spec_rcd_load( i_target, port_number, p_func_num_arr, func13_rcd_number_array_size, + func_rcd_control_word , ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + } // end # extended control words to write + // end Function 13 + + // set FN 0 via RC 7 + rcd0_15[0] = 0; + rcd0_15[1] = 0; + rc = mss_spec_rcd_load( i_target, port_number, &rcw, 1, rcd0_15, ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", + uint32_t(rc), rc.getCreator()); + return rc; + } + + // force execute of remaining rcd !! not necessary??? !! + // Execute the contents of CCS array + if (ccs_inst_cnt > 0) + { + // Set the End bit on the last CCS Instruction + rc = mss_ccs_set_end_bit( i_target, ccs_inst_cnt-1); + if(rc) + { + FAPI_ERR("CCS_SET_END_BIT FAILED rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + rc = mss_execute_ccs_inst_array(i_target, 10, 10); + if(rc) + { + FAPI_ERR(" EXECUTE_CCS_INST_ARRAY FAILED rc = 0x%08X (creator = %d)", + uint32_t(rc), rc.getCreator()); + return rc; + } + + ccs_inst_cnt = 0; + } + // end force execute of rcd + + + return rc; + +} + +fapi::ReturnCode mss_lrdimm_mrs_load( Target& i_target , uint32_t i_port_number,uint32_t dimm_number, uint32_t& io_ccs_inst_cnt) +{ + // For LRDIMM Set Rtt_nom, rtt_wr, driver impedance for R0 and R1 + // turn off MRS broadcast + ReturnCode rc; + ReturnCode rc_buff; + uint32_t rc_num = 0; + ecmdDataBufferBase csn_8(8); + rc_num = rc_num | csn_8.setBit(0,8); + ecmdDataBufferBase address_16(16); + ecmdDataBufferBase bank_3(3); + ecmdDataBufferBase activate_1(1); + ecmdDataBufferBase rasn_1(1); + rc_num = rc_num | rasn_1.clearBit(0); + ecmdDataBufferBase casn_1(1); + rc_num = rc_num | casn_1.clearBit(0); + ecmdDataBufferBase wen_1(1); + rc_num = rc_num | wen_1.clearBit(0); + ecmdDataBufferBase cke_4(4); + rc_num = rc_num | cke_4.setBit(0,4); + ecmdDataBufferBase odt_4(4); + rc_num = rc_num | odt_4.setBit(0,4); + ecmdDataBufferBase ddr_cal_type_4(4); + ecmdDataBufferBase csn_setup_8(8); + rc_num = rc_num | csn_setup_8.setBit(0,8); + + ecmdDataBufferBase num_idles_16(16); + rc_num = rc_num | num_idles_16.insertFromRight((uint32_t) 400, 0, 16); + ecmdDataBufferBase num_idles_setup_16(16); + rc_num = rc_num | num_idles_setup_16.insertFromRight((uint32_t) 400, 0, 16); + ecmdDataBufferBase num_repeat_16(16); + ecmdDataBufferBase data_20(20); + ecmdDataBufferBase read_compare_1(1); + ecmdDataBufferBase rank_cal_4(4); + ecmdDataBufferBase ddr_cal_enable_1(1); + ecmdDataBufferBase ccs_end_1(1); + + ecmdDataBufferBase mrs1(16); + uint16_t MRS1 = 0; + uint32_t mrs_number; + uint8_t address_mirror_map[2][2]; //address_mirror_map[port][dimm] + uint8_t is_sim = 0; + uint8_t dram_2n_mode = 0; + + uint32_t rank_number; + uint16_t num_ranks = 2; + uint8_t func13_rcd_number_array_size; + uint8_t func13_rcd_number_array_u8[4] = {10,11,14,15}; + ecmdDataBufferBase data_buff_rcd_word(64); + uint8_t l_rcd_cntl_word_7 = 0; + uint64_t func_rcd_control_word[2]; + uint8_t l_rcd_cntl_word_14; + uint64_t rcd_array[2][2]; //[port][dimm] + uint8_t num_ranks_array[2][2]; + + // cs 0:7 R0 R1 R2 R3 R4 R5 R6 R7 + uint8_t lrdimm_cs8n [] = { 0x4, 0x8, 0x6, 0xA, 0x5, 0x9, 0x7, 0xB }; + + rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target, num_ranks_array); + if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_RCD_CNTL_WORD_0_15, &i_target, rcd_array); + if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_ADDRESS_MIRRORING, &i_target, address_mirror_map); + if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_IS_SIMULATION, NULL, is_sim); + if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_2N_MODE_ENABLED, &i_target, dram_2n_mode); + if(rc) return rc; + + //MRS1 + uint8_t dll_enable; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_DLL_ENABLE, &i_target, dll_enable); + if(rc) return rc; + uint8_t out_drv_imp_cntl[2][2]; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_RON, &i_target, out_drv_imp_cntl); + if(rc) return rc; + uint8_t dram_rtt_nom[2][2][4]; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_RTT_NOM, &i_target, dram_rtt_nom); + if(rc) return rc; + uint8_t dram_al; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_AL, &i_target, dram_al); + if(rc) return rc; + uint8_t wr_lvl; //write leveling enable + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WR_LVL_ENABLE, &i_target, wr_lvl); + if(rc) return rc; + uint8_t tdqs_enable; //TDQS Enable + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_TDQS, &i_target, tdqs_enable); + if(rc) return rc; + uint8_t q_off; //Qoff - Output buffer Enable + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_OUTPUT_BUFFER, &i_target, q_off); + if(rc) return rc; + + + if (dll_enable == ENUM_ATTR_EFF_DRAM_DLL_ENABLE_ENABLE) + { + dll_enable = 0x00; + } + else if (dll_enable == ENUM_ATTR_EFF_DRAM_DLL_ENABLE_DISABLE) + { + dll_enable = 0xFF; + } + + if (dram_al == ENUM_ATTR_EFF_DRAM_AL_DISABLE) + { + dram_al = 0x00; + } + else if (dram_al == ENUM_ATTR_EFF_DRAM_AL_CL_MINUS_1) + { + dram_al = 0x80; + } + else if (dram_al == ENUM_ATTR_EFF_DRAM_AL_CL_MINUS_2) + { + dram_al = 0x40; + } + + if (wr_lvl == ENUM_ATTR_EFF_DRAM_WR_LVL_ENABLE_DISABLE) + { + wr_lvl = 0x00; + } + else if (wr_lvl == ENUM_ATTR_EFF_DRAM_WR_LVL_ENABLE_ENABLE) + { + wr_lvl = 0xFF; + } + + if (tdqs_enable == ENUM_ATTR_EFF_DRAM_TDQS_DISABLE) + { + tdqs_enable = 0x00; + } + else if (tdqs_enable == ENUM_ATTR_EFF_DRAM_TDQS_ENABLE) + { + tdqs_enable = 0xFF; + } + + if (q_off == ENUM_ATTR_EFF_DRAM_OUTPUT_BUFFER_DISABLE) + { + q_off = 0xFF; + } + else if (q_off == ENUM_ATTR_EFF_DRAM_OUTPUT_BUFFER_ENABLE) + { + q_off = 0x00; + } + + for (uint8_t dimm_num = 0;dimm_num < MAX_NUM_DIMMS; dimm_num++) + { + + if ( num_ranks_array[i_port_number][dimm_num] != 0 ) + { + l_rcd_cntl_word_14 = (rcd_array[i_port_number][dimm_num] & 0xF0) >> 4; // MRS broadcast + FAPI_INF("current F0RC14 = 0x%X",l_rcd_cntl_word_14); + l_rcd_cntl_word_14 = l_rcd_cntl_word_14 | 0x4; + FAPI_INF("setting F0RC14 = 0x%X",l_rcd_cntl_word_14); + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_14, 56,4); + func_rcd_control_word[dimm_num] = data_buff_rcd_word.getDoubleWord(0); + if(rc) return rc; + } + } + + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + + uint8_t *p_func_num_arr; + uint8_t func0_rcd_number_array_size = 2; + uint8_t func0_rcd_number_array_u8[] = { 7, 14 }; + p_func_num_arr = func0_rcd_number_array_u8; + rc = mss_spec_rcd_load(i_target, i_port_number, p_func_num_arr, func0_rcd_number_array_size, + func_rcd_control_word , io_ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + + // set FN 0 via RC 7 + func_rcd_control_word[0]=0; + func_rcd_control_word[1]=0; + func0_rcd_number_array_u8 [0] = 7; + rc = mss_spec_rcd_load( i_target, i_port_number, p_func_num_arr, 1, + func_rcd_control_word, io_ccs_inst_cnt,1); + + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + // end turn off MRS broadcast + + // Disable MRS snooping + l_rcd_cntl_word_7 = 13; + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + + // extended control word addr, data + uint8_t ext_func[2] = { 0xAC, 0x04}; // MRS_CTRL = 0xAC; snoop/forward/store + uint8_t rcw = 7; + uint64_t rcd0_15[2] = { 0x0000000D00000000ll, // select FN 13 dimm0 + 0x0000000D00000000ll }; // " dimm1 + + // set FN 13 via RC 7 + rc = mss_spec_rcd_load( i_target, i_port_number, &rcw, 1, rcd0_15, io_ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", + uint32_t(rc), rc.getCreator()); + return rc; + } + + func13_rcd_number_array_size = 4; + p_func_num_arr = func13_rcd_number_array_u8; + + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_7, 28,4); // select F13 + + // set func_rcd_control_word[dimm_number] + if ( num_ranks_array[i_port_number][dimm_number] != 0 ) { + // load address + data_buff_rcd_word.insertFromRight(ext_func[0],40,4); // lsb address + data_buff_rcd_word.insert(ext_func[0],44,4); // msb address + // load data + data_buff_rcd_word.insertFromRight(ext_func[1], 56,4); // lsb data + data_buff_rcd_word.insert(ext_func[1], 60,4); // msb data + + func_rcd_control_word[dimm_number] = data_buff_rcd_word.getDoubleWord(0); + if(rc) return rc; + } // end if has ranks + + // load CCS with F13 RC 10:11, 14:15 + rc = mss_spec_rcd_load( i_target, i_port_number, p_func_num_arr, func13_rcd_number_array_size, + func_rcd_control_word , io_ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + // set FN 0 via RC 7 + rcd0_15[0] = 0; + rcd0_15[1] = 0; + rc = mss_spec_rcd_load( i_target, i_port_number, &rcw, 1, rcd0_15, io_ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", + uint32_t(rc), rc.getCreator()); + return rc; + } + + // force execute of remaining rcd !! not necessary??? !! + // Execute the contents of CCS array + if (io_ccs_inst_cnt > 0) + { + // Set the End bit on the last CCS Instruction + rc = mss_ccs_set_end_bit( i_target, io_ccs_inst_cnt-1); + if(rc) + { + FAPI_ERR("CCS_SET_END_BIT FAILED rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + rc = mss_execute_ccs_inst_array(i_target, 10, 10); + if(rc) + { + FAPI_ERR(" EXECUTE_CCS_INST_ARRAY FAILED rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + io_ccs_inst_cnt = 0; + } + // end force execute of rcd + + // Set RTT_nom, rtt_wr, driver impdance through MR1 + for ( rank_number = 0; rank_number < num_ranks; rank_number++) + { + FAPI_INF( "MRS SETTINGS FOR PORT%d DIMM%d RANK%d", i_port_number, dimm_number, rank_number); + + rc_num = rc_num | csn_8.setBit(0,8); + rc_num = rc_num | address_16.clearBit(0, 16); + + if (dram_rtt_nom[i_port_number][dimm_number][rank_number] == ENUM_ATTR_EFF_DRAM_RTT_NOM_DISABLE) + { + dram_rtt_nom[i_port_number][dimm_number][rank_number] = 0x00; + } + else if (dram_rtt_nom[i_port_number][dimm_number][rank_number] == ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM20) + { + dram_rtt_nom[i_port_number][dimm_number][rank_number] = 0x20; + } + else if (dram_rtt_nom[i_port_number][dimm_number][rank_number] == ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM30) + { + dram_rtt_nom[i_port_number][dimm_number][rank_number] = 0xA0; + } + else if (dram_rtt_nom[i_port_number][dimm_number][rank_number] == ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM40) + { + dram_rtt_nom[i_port_number][dimm_number][rank_number] = 0xC0; + } + else if (dram_rtt_nom[i_port_number][dimm_number][rank_number] == ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM60) + { + dram_rtt_nom[i_port_number][dimm_number][rank_number] = 0x80; + } + else if (dram_rtt_nom[i_port_number][dimm_number][rank_number] == ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM120) + { + dram_rtt_nom[i_port_number][dimm_number][rank_number] = 0x40; + } + + if (out_drv_imp_cntl[i_port_number][dimm_number] == ENUM_ATTR_EFF_DRAM_RON_OHM40) + { + out_drv_imp_cntl[i_port_number][dimm_number] = 0x00; + } + else if (out_drv_imp_cntl[i_port_number][dimm_number] == ENUM_ATTR_EFF_DRAM_RON_OHM34) + { + out_drv_imp_cntl[i_port_number][dimm_number] = 0x80; + } + + + rc_num = rc_num | mrs1.insert((uint8_t) dll_enable, 0, 1, 0); + rc_num = rc_num | mrs1.insert((uint8_t) out_drv_imp_cntl[i_port_number][dimm_number], 1, 1, 0); + rc_num = rc_num | mrs1.insert((uint8_t) dram_rtt_nom[i_port_number][dimm_number][rank_number], 2, 1, 0); + rc_num = rc_num | mrs1.insert((uint8_t) dram_al, 3, 2, 0); + rc_num = rc_num | mrs1.insert((uint8_t) out_drv_imp_cntl[i_port_number][dimm_number], 5, 1, 1); + rc_num = rc_num | mrs1.insert((uint8_t) dram_rtt_nom[i_port_number][dimm_number][rank_number], 6, 1, 1); + rc_num = rc_num | mrs1.insert((uint8_t) wr_lvl, 7, 1, 0); + rc_num = rc_num | mrs1.insert((uint8_t) 0x00, 8, 1); + rc_num = rc_num | mrs1.insert((uint8_t) dram_rtt_nom[i_port_number][dimm_number][rank_number], 9, 1, 2); + rc_num = rc_num | mrs1.insert((uint8_t) 0x00, 10, 1); + rc_num = rc_num | mrs1.insert((uint8_t) tdqs_enable, 11, 1, 0); + rc_num = rc_num | mrs1.insert((uint8_t) q_off, 12, 1, 0); + rc_num = rc_num | mrs1.insert((uint8_t) 0x00, 13, 3); + + rc_num = rc_num | mrs1.extractPreserve(&MRS1, 0, 16, 0); + + FAPI_INF( "MRS 1: 0x%04X", MRS1); + + if (rc_num) + { + FAPI_ERR( "mss_mrs_load: Error setting up buffers"); + rc_buff.setEcmdError(rc_num); + return rc_buff; + } + + // Only corresponding CS to rank + rc_num = rc_num | csn_8.setBit(0,8); + rc_num = rc_num | csn_8.insert(lrdimm_cs8n[rank_number],(4*dimm_number),4,4); + mrs_number = 2; + + // Copying the current MRS into address buffer matching the MRS_array order + // Setting the bank address + rc_num = rc_num | address_16.insert(mrs1, 0, 16, 0); + rc_num = rc_num | bank_3.insert((uint8_t) MRS1_BA, 0, 1, 7); + rc_num = rc_num | bank_3.insert((uint8_t) MRS1_BA, 1, 1, 6); + rc_num = rc_num | bank_3.insert((uint8_t) MRS1_BA, 2, 1, 5); + + + if (rc_num) + { + FAPI_ERR( "mss_mrs_load: Error setting up buffers"); + rc_buff.setEcmdError(rc_num); + return rc_buff; + } + + if (( address_mirror_map[i_port_number][dimm_number] & (0x08 >> rank_number) ) && (is_sim == 0)) + { + rc = mss_address_mirror_swizzle(i_target, i_port_number, dimm_number, rank_number, address_16, bank_3); + } + + + if (dram_2n_mode == ENUM_ATTR_EFF_DRAM_2N_MODE_ENABLED_TRUE) + { + + // Send out to the CCS array + rc = mss_ccs_inst_arry_0( i_target, + io_ccs_inst_cnt, + address_16, + bank_3, + activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_setup_8, + odt_4, + ddr_cal_type_4, + i_port_number); + if(rc) return rc; + rc = mss_ccs_inst_arry_1( i_target, + io_ccs_inst_cnt, + num_idles_setup_16, + num_repeat_16, + data_20, + read_compare_1, + rank_cal_4, + ddr_cal_enable_1, + ccs_end_1); + if(rc) return rc; + io_ccs_inst_cnt ++; + } + + // Send out to the CCS array + rc = mss_ccs_inst_arry_0( i_target, + io_ccs_inst_cnt, + address_16, + bank_3, + activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + ddr_cal_type_4, + i_port_number); + if(rc) return rc; + rc = mss_ccs_inst_arry_1( i_target, + io_ccs_inst_cnt, + num_idles_16, + num_repeat_16, + data_20, + read_compare_1, + rank_cal_4, + ddr_cal_enable_1, + ccs_end_1); + if(rc) return rc; + io_ccs_inst_cnt ++; + + } // end rank loop + + // turn on MRS broadcast + + l_rcd_cntl_word_7 = 0; + + for (uint8_t dimm_num = 0;dimm_num < MAX_NUM_DIMMS; dimm_num++) + { + + if ( num_ranks_array[i_port_number][dimm_num] != 0 ) + { + l_rcd_cntl_word_14 = (rcd_array[i_port_number][dimm_num] & 0xF0) >> 4; // MRS broadcast + FAPI_INF("current F0RC14 = 0x%X",l_rcd_cntl_word_14); + l_rcd_cntl_word_14 = l_rcd_cntl_word_14 & 0xB; + FAPI_INF("setting F0RC14 = 0x%X",l_rcd_cntl_word_14); + ecmdDataBufferBase data_buff_rcd_word(64); + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_14, 56,4); + func_rcd_control_word[dimm_num] = data_buff_rcd_word.getDoubleWord(0); + if(rc) return rc; + } + } + + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + + func0_rcd_number_array_size = 2; + p_func_num_arr = func0_rcd_number_array_u8; + rc = mss_spec_rcd_load(i_target, i_port_number, p_func_num_arr, func0_rcd_number_array_size, + func_rcd_control_word , io_ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + + // set FN 0 via RC 7 + func_rcd_control_word[0]=0; + func_rcd_control_word[1]=0; + func0_rcd_number_array_u8 [0] = 7; + rc = mss_spec_rcd_load( i_target, i_port_number, p_func_num_arr, 1, + func_rcd_control_word, io_ccs_inst_cnt,1); + + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + // end turn on MRS broadcast + + // Enable MRS snooping + l_rcd_cntl_word_7 = 13; + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + + // extended control word data + ext_func[1] = 0x00; // MRS_CTRL = 0xAC; snoop/forward/store + rcw = 7; + rcd0_15[0] = 0x0000000D00000000ll; // select FN 13 dimm0 + rcd0_15[1] = 0x0000000D00000000ll ; // " dimm1 + + // set FN 13 via RC 7 + rc = mss_spec_rcd_load( i_target, i_port_number, &rcw, 1, rcd0_15, io_ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", + uint32_t(rc), rc.getCreator()); + return rc; + } + + func13_rcd_number_array_size = 4; + p_func_num_arr = func13_rcd_number_array_u8; + + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_7, 28,4); // select F13 + + // set func_rcd_control_word[dimm_number] + if ( num_ranks_array[i_port_number][dimm_number] != 0 ) { + // load address + data_buff_rcd_word.insertFromRight(ext_func[0],40,4); // lsb address + data_buff_rcd_word.insert(ext_func[0],44,4); // msb address + // load data + data_buff_rcd_word.insertFromRight(ext_func[1], 56,4); // lsb data + data_buff_rcd_word.insert(ext_func[1], 60,4); // msb data + + func_rcd_control_word[dimm_number] = data_buff_rcd_word.getDoubleWord(0); if(rc) return rc; + } // end if has ranks + + + // load CCS with F13 RC 10:11, 14:15 + rc = mss_spec_rcd_load( i_target, i_port_number, p_func_num_arr, func13_rcd_number_array_size, + func_rcd_control_word , io_ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + // set FN 0 via RC 7 + rcd0_15[0] = 0; + rcd0_15[1] = 0; + rc = mss_spec_rcd_load( i_target, i_port_number, &rcw, 1, rcd0_15, io_ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", + uint32_t(rc), rc.getCreator()); + return rc; + } + + // force execute of remaining rcd !! not necessary??? !! + // Execute the contents of CCS array + if (io_ccs_inst_cnt > 0) + { + // Set the End bit on the last CCS Instruction + rc = mss_ccs_set_end_bit( i_target, io_ccs_inst_cnt-1); + if(rc) + { + FAPI_ERR("CCS_SET_END_BIT FAILED rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + rc = mss_execute_ccs_inst_array(i_target, 10, 10); + if(rc) + { + FAPI_ERR(" EXECUTE_CCS_INST_ARRAY FAILED rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + io_ccs_inst_cnt = 0; + } + // end force execute of rcd + // End enable MRS snooping + + + return rc; +} + +fapi::ReturnCode mss_execute_lrdimm_mb_dram_training(Target &i_target) +{ + ReturnCode rc; + uint8_t l_rcd_cntl_word_7; + uint8_t l_rcd_cntl_word_12; + ecmdDataBufferBase data_buff_rcd_word(64); + uint32_t port; + uint8_t dimm_number; + const uint8_t MAX_NUM_DIMMS = 2; + const uint8_t MAX_NUM_PORT = 2; + uint8_t num_ranks_array[MAX_NUM_PORT][MAX_NUM_DIMMS]; + uint64_t func_rcd_control_word[2]; + uint8_t *p_func_num_arr; + uint8_t funcTRAIN_rcd_number_array_u8[2] = {7,12}; + + uint32_t ccs_inst_cnt = 0; + uint32_t rc_num = 0; + ecmdDataBufferBase address_16(16); + ecmdDataBufferBase bank_3(3); + ecmdDataBufferBase activate_1(1); + ecmdDataBufferBase rasn_1(1); + rc_num = rc_num | rasn_1.setBit(0); + ecmdDataBufferBase casn_1(1); + rc_num = rc_num | casn_1.setBit(0); + ecmdDataBufferBase wen_1(1); + rc_num = rc_num | wen_1.setBit(0); + ecmdDataBufferBase cke_4(4); + rc_num = rc_num | cke_4.setBit(0,4); + ecmdDataBufferBase csn_8(8); + rc_num = rc_num | csn_8.setBit(0,2); + rc_num = rc_num | csn_8.setBit(4,2); + ecmdDataBufferBase odt_4(4); + rc_num = rc_num | odt_4.setBit(0,4); + ecmdDataBufferBase ddr_cal_type_4(4); + + if(rc_num) + { + rc.setEcmdError(rc_num); + return rc; + } + ecmdDataBufferBase num_idles_16(16); + ecmdDataBufferBase num_repeat_16(16); + ecmdDataBufferBase data_20(20); + ecmdDataBufferBase read_compare_1(1); + ecmdDataBufferBase rank_cal_4(4); + ecmdDataBufferBase ddr_cal_enable_1(1); + ecmdDataBufferBase ccs_end_1(1); + + uint32_t l_mss_freq; + uint32_t l_num_idles_delay=20; + + fapi::Target l_target_centaur; + rc = fapiGetParentChip(i_target, l_target_centaur); + if(rc) return rc; + + rc = FAPI_ATTR_GET(ATTR_MSS_FREQ, &l_target_centaur, l_mss_freq); + if(rc) return rc; + + rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target, num_ranks_array); + if(rc) return rc; + + for ( port = 0; port < MAX_NUM_PORT; port++ ) + { + // MB-DRAM training + l_rcd_cntl_word_7 = 0; + l_rcd_cntl_word_12 = 2; // Training control, start DRAM interface training + + data_buff_rcd_word.clearBit(0,64); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_7, 28, 4); + data_buff_rcd_word.insertFromRight(&l_rcd_cntl_word_12, 48, 4); + + for ( dimm_number = 0; dimm_number < MAX_NUM_DIMMS; dimm_number++ ) + { + if ( num_ranks_array[port][dimm_number] != 0 ) + { + func_rcd_control_word[dimm_number] = data_buff_rcd_word.getDoubleWord(0); + if(rc) return rc; + } + } + + FAPI_INF("SELECTING FUNCTION %d", l_rcd_cntl_word_7); + p_func_num_arr = funcTRAIN_rcd_number_array_u8; + rc = mss_spec_rcd_load(i_target, port, p_func_num_arr, + (uint8_t) sizeof(funcTRAIN_rcd_number_array_u8)/(uint8_t)sizeof(funcTRAIN_rcd_number_array_u8[0]), + func_rcd_control_word , ccs_inst_cnt,1); + if(rc) + { + FAPI_ERR(" spec_rcd_load Failed rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + + rc_num = rc_num | address_16.clearBit(0, 16); + rc_num = rc_num | num_idles_16.insertFromRight((uint32_t) l_num_idles_delay, 0, 16); + if(rc_num) + { + rc.setEcmdError(rc_num); + return rc; + } + + rc = mss_ccs_inst_arry_0( i_target, + ccs_inst_cnt, + address_16, + bank_3, + activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + ddr_cal_type_4, + port); + if(rc) return rc; + rc = mss_ccs_inst_arry_1( i_target, + ccs_inst_cnt, + num_idles_16, + num_repeat_16, + data_20, + read_compare_1, + rank_cal_4, + ddr_cal_enable_1, + ccs_end_1); + if(rc) return rc; + ccs_inst_cnt++; + } + + // Execute the contents of CCS array + if (ccs_inst_cnt > 0) + { + // Set the End bit on the last CCS Instruction + rc = mss_ccs_set_end_bit( i_target, ccs_inst_cnt-1); + if(rc) + { + FAPI_ERR("CCS_SET_END_BIT FAILED rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + rc = mss_execute_ccs_inst_array(i_target, 10, 10); + if(rc) + { + FAPI_ERR(" EXECUTE_CCS_INST_ARRAY FAILED rc = 0x%08X (creator = %d)", uint32_t(rc), rc.getCreator()); + return rc; + } + + ccs_inst_cnt = 0; + }// end force execute of rcd + return rc; +} + +fapi::ReturnCode mss_lrdimm_eff_config(const Target &i_target_mba, + uint8_t cur_dimm_spd_valid_u8array[PORT_SIZE][DIMM_SIZE], + uint32_t mss_freq, uint8_t eff_num_ranks_per_dimm[PORT_SIZE][DIMM_SIZE]) +{ + ReturnCode rc; + + std::vector<fapi::Target> l_target_dimm_array; + uint8_t l_cur_mba_port = 0; + uint8_t l_cur_mba_dimm = 0; + + mss_lrdimm_spd_data *p_l_lr_spd_data = new mss_lrdimm_spd_data(); + memset( p_l_lr_spd_data, 0, sizeof(mss_lrdimm_spd_data) ); + + uint8_t lrdimm_mr12_reg[PORT_SIZE][DIMM_SIZE]; + uint64_t lrdimm_additional_cntl_words[PORT_SIZE][DIMM_SIZE]; + uint8_t lrdimm_rank_mult_mode; + uint8_t eff_ibm_type[PORT_SIZE][DIMM_SIZE]; + uint64_t eff_dimm_rcd_cntl_word_0_15[PORT_SIZE][DIMM_SIZE]; + + do + { + rc = fapiGetAssociatedDimms(i_target_mba, l_target_dimm_array); + if(rc) + { + FAPI_ERR("Error retrieving assodiated dimms"); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); + break; + } + + for (uint8_t l_dimm_index = 0; l_dimm_index < l_target_dimm_array.size(); l_dimm_index += 1) + { + rc = FAPI_ATTR_GET(ATTR_MBA_PORT, &l_target_dimm_array[l_dimm_index], + l_cur_mba_port); + if(rc) + { + FAPI_ERR("Error retrieving ATTR_MBA_PORT"); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); + break; + } + //------------------------------------------------------------------------ + rc = FAPI_ATTR_GET(ATTR_MBA_DIMM, &l_target_dimm_array[l_dimm_index], l_cur_mba_dimm); + if(rc) + { + FAPI_ERR("Error retrieving ATTR_MBA_DIMM"); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); + break; + } + + // Setup SPD attributes + rc = FAPI_ATTR_GET(ATTR_SPD_LR_ADDR_MIRRORING, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_addr_mirroring[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F0RC3_F0RC2, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f0rc3_f0rc2[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F0RC5_F0RC4, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f0rc5_f0rc4[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F1RC11_F1RC8, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f1rc11_f1rc8[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F1RC13_F1RC12, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f1rc13_f1rc12[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F1RC15_F1RC14, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f1rc15_f1rc14[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F3RC9_F3RC8_FOR_800_1066, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f3rc9_f3rc8_for_800_1066[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F34RC11_F34RC10_FOR_800_1066, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f34rc11_f34rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F56RC11_F56RC10_FOR_800_1066, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f56rc11_f56rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F78RC11_F78RC10_FOR_800_1066, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f78rc11_f78rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F910RC11_F910RC10_FOR_800_1066, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f910rc11_f910rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_MR12_FOR_800_1066, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_mr12_for_800_1066[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F3RC9_F3RC8_FOR_1333_1600, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f3rc9_f3rc8_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F34RC11_F34RC10_FOR_1333_1600, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f34rc11_f34rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F56RC11_F56RC10_FOR_1333_1600, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f56rc11_f56rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F78RC11_F78RC10_FOR_1333_1600, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f78rc11_f78rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F910RC11_F910RC10_FOR_1333_1600, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f910rc11_f910rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_MR12_FOR_1333_1600, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_mr12_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F3RC9_F3RC8_FOR_1866_2133, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f3rc9_f3rc8_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F34RC11_F34RC10_FOR_1866_2133, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f34rc11_f34rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F56RC11_F56RC10_FOR_1866_2133, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f56rc11_f56rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F78RC11_F78RC10_FOR_1866_2133, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f78rc11_f78rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_F910RC11_F910RC10_FOR_1866_2133, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_f910rc11_f910rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + rc = FAPI_ATTR_GET(ATTR_SPD_LR_MR12_FOR_1866_2133, &l_target_dimm_array[l_dimm_index], + p_l_lr_spd_data->lr_mr12_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm]); + if(rc) break; + } + + if(rc) + { + FAPI_ERR("Error reading spd data from caller"); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); + break; + } + + + // Setup attributes + for (int l_cur_mba_port = 0; l_cur_mba_port < PORT_SIZE; l_cur_mba_port += 1) + { + for (int l_cur_mba_dimm = 0; l_cur_mba_dimm < DIMM_SIZE; l_cur_mba_dimm += 1) + { + if (cur_dimm_spd_valid_u8array[l_cur_mba_port][l_cur_mba_dimm] == MSS_EFF_VALID) + { + FAPI_INF(" !! LRDIMM Detected -MW"); + + ecmdDataBuffer rcd(64); + rcd.flushTo0(); + + rcd.setDoubleWord(0,eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm]); + FAPI_INF("rcd0_15=0x%016llX",rcd.getDoubleWord(0)); + + rcd.insert(p_l_lr_spd_data->lr_f0rc3_f0rc2[l_cur_mba_port][l_cur_mba_dimm],12,4,0); //rcd3 + rcd.insert(p_l_lr_spd_data->lr_f0rc3_f0rc2[l_cur_mba_port][l_cur_mba_dimm],8,4,4); //rcd2 + + rcd.insert(p_l_lr_spd_data->lr_f0rc5_f0rc4[l_cur_mba_port][l_cur_mba_dimm],20,4,0); //rcd5 + rcd.insert(p_l_lr_spd_data->lr_f0rc5_f0rc4[l_cur_mba_port][l_cur_mba_dimm],16,4,4); //rcd4 + + rcd.insert(p_l_lr_spd_data->lr_addr_mirroring[l_cur_mba_port][l_cur_mba_dimm],59,1,7); // address mirroring + + eff_dimm_rcd_cntl_word_0_15[l_cur_mba_port][l_cur_mba_dimm]=rcd.getDoubleWord(0); + + ecmdDataBuffer rcd_1(64); + rcd_1.flushTo0(); + // F[1]RC11,8 + rcd_1.insert(p_l_lr_spd_data->lr_f1rc11_f1rc8[l_cur_mba_port][l_cur_mba_dimm],44,4,0); //F[1]RC11 -> rcd11 + rcd_1.insert(p_l_lr_spd_data->lr_f1rc11_f1rc8[l_cur_mba_port][l_cur_mba_dimm],32,4,4); //F[1]RC8 -> rcd8 + + // F[1]RC13,12 + rcd_1.insert(p_l_lr_spd_data->lr_f1rc13_f1rc12[l_cur_mba_port][l_cur_mba_dimm],52,4,0); //F[1]RC13 -> rcd13 + rcd_1.insert(p_l_lr_spd_data->lr_f1rc13_f1rc12[l_cur_mba_port][l_cur_mba_dimm],48,4,4); //F[1]RC12 -> rcd12 + + // F[1]RC15,14 + rcd_1.insert(p_l_lr_spd_data->lr_f1rc15_f1rc14[l_cur_mba_port][l_cur_mba_dimm],60,4,0); //F[1]RC15 -> rcd15 + rcd_1.insert(p_l_lr_spd_data->lr_f1rc15_f1rc14[l_cur_mba_port][l_cur_mba_dimm],56,4,4); //F[1]RC14 -> rcd14 + + + if ( mss_freq > 1733 ) { + rcd_1.insert(p_l_lr_spd_data->lr_f3rc9_f3rc8_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],36,4,0); // F[3]RC9 -> rcd9 + rcd_1.insert(p_l_lr_spd_data->lr_f3rc9_f3rc8_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],40,4,4); // F[3]RC8 -> rcd10 + rcd_1.insert(p_l_lr_spd_data->lr_f34rc11_f34rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],4,4,0); // F[3,4]RC11 -> rcd1 + rcd_1.insert(p_l_lr_spd_data->lr_f34rc11_f34rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],0,4,4); // F[3,4]RC10 -> rcd0 + rcd_1.insert(p_l_lr_spd_data->lr_f56rc11_f56rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],12,4,0); // F[6,6]RC11 -> rcd3 + rcd_1.insert(p_l_lr_spd_data->lr_f56rc11_f56rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],8,4,4); // F[5,6]RC10 -> rcd2 + rcd_1.insert(p_l_lr_spd_data->lr_f78rc11_f78rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],20,4,0); // F[7,8]RC11 -> rcd5 + rcd_1.insert(p_l_lr_spd_data->lr_f78rc11_f78rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],16,4,4); // F[7,8]RC10 -> rcd4 + rcd_1.insert(p_l_lr_spd_data->lr_f910rc11_f910rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],28,4,0); // F[9,10]RC11 -> rcd7 + rcd_1.insert(p_l_lr_spd_data->lr_f910rc11_f910rc10_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm],24,4,4); // F[9,10]RC10 -> rcd6 + + lrdimm_mr12_reg[l_cur_mba_port][l_cur_mba_dimm] = p_l_lr_spd_data->lr_mr12_for_1866_2133[l_cur_mba_port][l_cur_mba_dimm]; + + } else if ( mss_freq > 1200 ) { + rcd_1.insert(p_l_lr_spd_data->lr_f3rc9_f3rc8_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],36,4,0); // F[3]RC9 -> rcd9 + rcd_1.insert(p_l_lr_spd_data->lr_f3rc9_f3rc8_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],40,4,4); // F[3]RC8 -> rcd10 + rcd_1.insert(p_l_lr_spd_data->lr_f34rc11_f34rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],4,4,0); // F[3,4]RC11 -> rcd1 + rcd_1.insert(p_l_lr_spd_data->lr_f34rc11_f34rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],0,4,4); // F[3,4]RC10 -> rcd0 + rcd_1.insert(p_l_lr_spd_data->lr_f56rc11_f56rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],12,4,0); // F[6,6]RC11 -> rcd3 + rcd_1.insert(p_l_lr_spd_data->lr_f56rc11_f56rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],8,4,4); // F[5,6]RC10 -> rcd2 + rcd_1.insert(p_l_lr_spd_data->lr_f78rc11_f78rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],20,4,0); // F[7,8]RC11 -> rcd5 + rcd_1.insert(p_l_lr_spd_data->lr_f78rc11_f78rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],16,4,4); // F[7,8]RC10 -> rcd4 + rcd_1.insert(p_l_lr_spd_data->lr_f910rc11_f910rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],28,4,0); // F[9,10]RC11 -> rcd7 + rcd_1.insert(p_l_lr_spd_data->lr_f910rc11_f910rc10_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm],24,4,4); // F[9,10]RC10 -> rcd6 + + lrdimm_mr12_reg[l_cur_mba_port][l_cur_mba_dimm] = p_l_lr_spd_data->lr_mr12_for_1333_1600[l_cur_mba_port][l_cur_mba_dimm]; + + } else { + rcd_1.insert(p_l_lr_spd_data->lr_f3rc9_f3rc8_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],36,4,0); // F[3]RC9 -> rcd9 + rcd_1.insert(p_l_lr_spd_data->lr_f3rc9_f3rc8_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],40,4,4); // F[3]RC8 -> rcd10 + rcd_1.insert(p_l_lr_spd_data->lr_f34rc11_f34rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],4,4,0); // F[3,4]RC11 -> rcd1 + rcd_1.insert(p_l_lr_spd_data->lr_f34rc11_f34rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],0,4,4); // F[3,4]RC10 -> rcd0 + rcd_1.insert(p_l_lr_spd_data->lr_f56rc11_f56rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],12,4,0); // F[6,6]RC11 -> rcd3 + rcd_1.insert(p_l_lr_spd_data->lr_f56rc11_f56rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],8,4,4); // F[5,6]RC10 -> rcd2 + rcd_1.insert(p_l_lr_spd_data->lr_f78rc11_f78rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],20,4,0); // F[7,8]RC11 -> rcd5 + rcd_1.insert(p_l_lr_spd_data->lr_f78rc11_f78rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],16,4,4); // F[7,8]RC10 -> rcd4 + rcd_1.insert(p_l_lr_spd_data->lr_f910rc11_f910rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],28,4,0); // F[9,10]RC11 -> rcd7 + rcd_1.insert(p_l_lr_spd_data->lr_f910rc11_f910rc10_for_800_1066[l_cur_mba_port][l_cur_mba_dimm],24,4,4); // F[9,10]RC10 -> rcd6 + + lrdimm_mr12_reg[l_cur_mba_port][l_cur_mba_dimm] = p_l_lr_spd_data->lr_mr12_for_800_1066[l_cur_mba_port][l_cur_mba_dimm]; + } + + uint64_t rcd1 = rcd_1.getDoubleWord(0); + lrdimm_additional_cntl_words[l_cur_mba_port][l_cur_mba_dimm] = rcd1; + + if ( eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 8 ) { + lrdimm_rank_mult_mode = 4; // Default for 8R is 4x mult mode + } + + // ======================================================================================== + + + // FIX finding stack type properly. + if ( eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 1 ) { + //p_o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_STACK_TYPE_NONE; + eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_IBM_TYPE_TYPE_5A; + } else if ( eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 2 ) { + //p_o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_STACK_TYPE_NONE; + eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_IBM_TYPE_TYPE_5B; + } else if ( eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 4 ) { + //p_o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_STACK_TYPE_DDP_QDP; + eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_IBM_TYPE_TYPE_5C; + } else if ( eff_num_ranks_per_dimm[l_cur_mba_port][l_cur_mba_dimm] == 8 ) { + //p_o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_STACK_TYPE_DDP_QDP; + eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_IBM_TYPE_TYPE_5D; + } else { + //p_o_atts->eff_stack_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_STACK_TYPE_NONE; + eff_ibm_type[l_cur_mba_port][l_cur_mba_dimm] = fapi::ENUM_ATTR_EFF_IBM_TYPE_UNDEFINED; + FAPI_ERR("Currently unsupported IBM_TYPE on %s!", i_target_mba.toEcmdString()); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); return rc; + } + } // end valid dimm + } // end dimm loop + } // end port loop + + rc = FAPI_ATTR_SET(ATTR_EFF_IBM_TYPE, &i_target_mba, + eff_ibm_type); + rc = FAPI_ATTR_SET(ATTR_LRDIMM_MR12_REG, &i_target_mba, + lrdimm_mr12_reg); + rc = FAPI_ATTR_SET(ATTR_LRDIMM_ADDITIONAL_CNTL_WORDS, &i_target_mba, + lrdimm_additional_cntl_words); + rc = FAPI_ATTR_SET(ATTR_LRDIMM_RANK_MULT_MODE, &i_target_mba, + lrdimm_rank_mult_mode); + rc = FAPI_ATTR_SET(ATTR_EFF_DIMM_RCD_CNTL_WORD_0_15, &i_target_mba, + eff_dimm_rcd_cntl_word_0_15); + + if(rc) + { + FAPI_ERR("Error setting attributes"); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); + break; + } + } while(0); + + return rc; +} + +fapi::ReturnCode mss_lrdimm_rewrite_odt( const Target& i_target_mba, uint32_t * p_b_var_array, uint32_t *var_array_p_array[5]) +{ + ReturnCode rc; + uint8_t l_num_ranks_per_dimm_u8array[PORT_SIZE][DIMM_SIZE]; + uint8_t l_arr_offset; + uint32_t l_mss_freq = 0; + uint8_t l_dram_width_u8; + + uint32_t *odt_array; + + // For dual drop, Set ODT_RD as 2rank (8R LRDIMM) or 4rank (4R LRDIMM) + fapi::Target l_target_centaur; + rc = fapiGetParentChip(i_target_mba, l_target_centaur); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_MSS_FREQ, &l_target_centaur, l_mss_freq); if(rc) return rc; + + rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target_mba, l_num_ranks_per_dimm_u8array); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target_mba, l_dram_width_u8); if(rc) return rc; + + uint8_t l_start=44, l_end=60; + if ( (l_num_ranks_per_dimm_u8array[0][1] == 4) || (l_num_ranks_per_dimm_u8array[1][1] == 4) ) { + odt_array = var_array_p_array[0]; + FAPI_INF("Setting LRDIMM ODT_RD as 4 rank dimm"); + } else if ( (l_num_ranks_per_dimm_u8array[0][1] == 8) || (l_num_ranks_per_dimm_u8array[1][1] == 8) ) { + if ( l_mss_freq <= 1466 ) { // 1333Mbps + if ( l_dram_width_u8 == 4 ) { + odt_array = var_array_p_array[1]; + } else if ( l_dram_width_u8 == 8 ) { + odt_array = var_array_p_array[2]; + } + } else if ( l_mss_freq <= 1733 ) { // 1600 Mbps + if ( l_dram_width_u8 == 4 ) { + odt_array = var_array_p_array[3]; + } else if ( l_dram_width_u8 == 8 ) { + odt_array = var_array_p_array[4]; + } + } + FAPI_INF("Setting LRDIMM ODT_RD as 2 logical rank dimm"); + } + + for ( l_arr_offset = l_start; l_arr_offset < l_end; l_arr_offset++ ) { + *(p_b_var_array + l_arr_offset) = *(odt_array + l_arr_offset); + } + + return rc; +} + +fapi::ReturnCode mss_lrdimm_term_atts(const Target& i_target_mba) +{ + ReturnCode rc; + + uint8_t l_dram_ron[PORT_SIZE][DIMM_SIZE]; + uint8_t l_dram_rtt_wr[PORT_SIZE][DIMM_SIZE]; + uint8_t l_dram_rtt_nom[PORT_SIZE][DIMM_SIZE]; + + uint8_t attr_eff_dram_ron[PORT_SIZE][DIMM_SIZE]; + uint8_t attr_eff_dram_rtt_nom[PORT_SIZE][DIMM_SIZE][RANK_SIZE]; + uint8_t attr_eff_dram_rtt_wr[PORT_SIZE][DIMM_SIZE][RANK_SIZE]; + uint8_t attr_eff_odt_wr[PORT_SIZE][DIMM_SIZE][RANK_SIZE]; + + uint32_t l_mss_freq = 0; + uint32_t l_mss_volt = 0; + uint8_t l_num_ranks_per_dimm_u8array[PORT_SIZE][DIMM_SIZE]; + uint8_t l_num_drops_per_port; + uint8_t l_dram_density; + uint8_t l_dram_width_u8; + + uint8_t l_lrdimm_mr12_u8array[PORT_SIZE][DIMM_SIZE]; + uint8_t l_lrdimm_rank_mult_mode; + + uint8_t l_rcd_cntl_word_0_1; + uint8_t l_rcd_cntl_word_6_7; + uint8_t l_rcd_cntl_word_8_9; + uint8_t l_rcd_cntl_word_10; + uint8_t l_rcd_cntl_word_11; + uint8_t l_rcd_cntl_word_12; + uint8_t l_rcd_cntl_word_13; + uint8_t l_rcd_cntl_word_14; + uint8_t l_rcd_cntl_word_15; + uint64_t l_rcd_cntl_word_0_15; + uint64_t l_rcd_cntl_word_2_5_mask = 0x00FFFF0000000010LL; + ecmdDataBufferBase data_buffer_64(64); + ecmdDataBufferBase data_buffer_8(8); + + // Fetch impacted attributes + uint64_t l_attr_eff_dimm_rcd_cntl_word_0_15[PORT_SIZE][DIMM_SIZE]; + rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_RCD_CNTL_WORD_0_15, &i_target_mba, l_attr_eff_dimm_rcd_cntl_word_0_15); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_RON, &i_target_mba, attr_eff_dram_ron); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_RTT_NOM, &i_target_mba, attr_eff_dram_rtt_nom); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_RTT_WR, &i_target_mba, attr_eff_dram_rtt_wr); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_ODT_WR, &i_target_mba, attr_eff_odt_wr); if(rc) return rc; + + // Fetch impacted attributes + rc = FAPI_ATTR_GET(ATTR_EFF_NUM_DROPS_PER_PORT, &i_target_mba, l_num_drops_per_port); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target_mba, l_dram_width_u8); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target_mba, l_num_ranks_per_dimm_u8array); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_DENSITY, &i_target_mba, l_dram_density); if(rc) return rc; + + fapi::Target l_target_centaur; + rc = fapiGetParentChip(i_target_mba, l_target_centaur); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_MSS_FREQ, &l_target_centaur, l_mss_freq); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_MSS_VOLT, &l_target_centaur, l_mss_volt); if(rc) return rc; + + // Fetch SPD MR1,2 + rc = FAPI_ATTR_GET(ATTR_LRDIMM_MR12_REG, &i_target_mba, l_lrdimm_mr12_u8array); if(rc) return rc; + rc = FAPI_ATTR_GET(ATTR_LRDIMM_RANK_MULT_MODE, &i_target_mba, l_lrdimm_rank_mult_mode); if(rc) return rc; + + for (uint8_t l_port = 0; l_port < PORT_SIZE; l_port++) { + for (uint8_t l_dimm = 0; l_dimm < DIMM_SIZE; l_dimm++) { + + // Set RCD control word + FAPI_INF("before setting: rcd control word 0-15 %.16llX", l_attr_eff_dimm_rcd_cntl_word_0_15[l_port][l_dimm] ); + l_rcd_cntl_word_0_1 = 0x00; // Global features, Clock driver enable + FAPI_INF("rcd control word 0-1 %X", l_rcd_cntl_word_0_1 ); + + // RCD cntl words 2-5 from SPD + + l_rcd_cntl_word_6_7 = 0x00; // CKE & ODT management, Function select + FAPI_INF("rcd control word 6-7 %X", l_rcd_cntl_word_6_7 ); + + if ( l_num_drops_per_port == fapi::ENUM_ATTR_EFF_NUM_DROPS_PER_PORT_DUAL ) { + l_rcd_cntl_word_8_9 = 0x20; // IBT=200 Ohm & Vref settings for address, command, par_in, Power saving settings + } + else { + l_rcd_cntl_word_8_9 = 0x00; // IBT=100 Ohm & Vref settings for address, command, par_in, Power saving settings + } + FAPI_INF("rcd control word 8-9 %X", l_rcd_cntl_word_8_9 ); + + + // RC10 LRDIMM operating speed + if ( l_mss_freq <= 933 ) { // 800Mbps + l_rcd_cntl_word_10 = 0; + } else if ( l_mss_freq <= 1200 ) { // 1066Mbps + l_rcd_cntl_word_10 = 1; + } else if ( l_mss_freq <= 1466 ) { // 1333Mbps + l_rcd_cntl_word_10 = 2; + } else if ( l_mss_freq <= 1733 ) { // 1600Mbps + l_rcd_cntl_word_10 = 3; + } else if ( l_mss_freq <= 2000 ) { // 1866Mbps + l_rcd_cntl_word_10 = 4; + } else { + FAPI_ERR("Invalid LRDIMM ATTR_MSS_FREQ = %d on %s!", l_mss_freq, i_target_mba.toEcmdString()); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); return rc; + } + FAPI_INF("rcd control word 10 %X", l_rcd_cntl_word_10 ); + + // RC11 Operating voltage & parity calculation (buffer does not include A17:16) + if ( l_mss_volt >= 1420 ) { // 1.5V + l_rcd_cntl_word_11 = 4; + } else if ( l_mss_volt >= 1270 ) { // 1.35V + l_rcd_cntl_word_11 = 5; + } else if ( l_mss_volt >= 1170 ) { // 1.25V + l_rcd_cntl_word_11 = 6; + } else { + FAPI_ERR("Invalid LRDIMM ATTR_MSS_VOLT = %d on %s!", l_mss_volt, i_target_mba.toEcmdString()); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); return rc; + } + FAPI_INF("rcd control word 11 %X", l_rcd_cntl_word_11 ); + + l_rcd_cntl_word_12 = 0; //Training + FAPI_INF("rcd control word 12 %X", l_rcd_cntl_word_12 ); + + // rC13 DIMM configuration + if ( l_num_ranks_per_dimm_u8array[l_port][l_dimm] == 8 ) { + l_rcd_cntl_word_13 = 4; // 8 physical ranks, 2 logical ranks, RM=4 + } else if ( l_num_ranks_per_dimm_u8array[l_port][l_dimm] == 4 ) { + l_rcd_cntl_word_13 = 9; // 4 physical ranks, 4 logical ranks, direct rank mapping + // } else if ( l_num_ranks_per_dimm_u8array[l_port][l_dimm] == 2 ) { + // l_rcd_cntl_word_13 = 6; // 2 physical ranks, 2 logical ranks, direct rank mapping + // } else if ( l_num_ranks_per_dimm_u8array[l_port][l_dimm] == 1 ) { + // l_rcd_cntl_word_13 = 3; // 1 physical rank, 1 logical rank, direct rank mapping + } else { + l_rcd_cntl_word_13 = 0; + } + FAPI_INF("rcd control word 13 %X", l_rcd_cntl_word_13 ); + + // RC14 DRAM configuration & DRAM command + if ( l_lrdimm_rank_mult_mode != 0 ) { + data_buffer_8.setBit(2); // turn off refresh broadcast + } + if ( l_dram_width_u8 == 8 ) { + data_buffer_8.setBit(0); + } + data_buffer_8.extractToRight( &l_rcd_cntl_word_14, 0, 4); + FAPI_INF("rcd control word 14 %X", l_rcd_cntl_word_14 ); + + // RC15 Rank multiplication + if ( l_lrdimm_rank_mult_mode == 4 ) { + if ( l_dram_density == 1 ) { + l_rcd_cntl_word_15 = 5; // A[15:14]; 4x multiplication, 1 Gbit DDR3 SDRAM + } else if ( l_dram_density == 2 ) { + l_rcd_cntl_word_15 = 6; // A[16:15]; 4x multiplication, 2 Gbit DDR3 SDRAM + } else if ( l_dram_density == 4 ) { + l_rcd_cntl_word_15 = 7; // A[17:16]; 4x multiplication, 4 Gbit DDR3 SDRAM + } else { + FAPI_ERR("Invalid LRDIMM Rank mult mode =%d, ATTR_EFF_DRAM_DENSITY = %d on %s!", l_lrdimm_rank_mult_mode, l_dram_density, i_target_mba.toEcmdString()); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); return rc; + } + } else if ( l_lrdimm_rank_mult_mode == 2 ) { + if ( l_dram_density == 1 ) { + l_rcd_cntl_word_15 = 1; // A[14]; 2x multiplication, 1 Gbit DDR3 SDRAM + } else if ( l_dram_density == 2 ) { + l_rcd_cntl_word_15 = 2; // A[15]; 2x multiplication, 2 Gbit DDR3 SDRAM + } else if ( l_dram_density == 4 ) { + l_rcd_cntl_word_15 = 3; // A[16]; 2x multiplication, 4 Gbit DDR3 SDRAM + } else { + FAPI_ERR("Invalid LRDIMM Rank Mult mode = %d, ATTR_EFF_DRAM_DENSITY = %d on %s!", l_lrdimm_rank_mult_mode, l_dram_density, i_target_mba.toEcmdString()); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); return rc; + } + } else { + l_rcd_cntl_word_15 = 0; + } + FAPI_INF("rcd control word 15 %X", l_rcd_cntl_word_15 ); + + data_buffer_64.insertFromRight(&l_rcd_cntl_word_0_1, 0, 8); + data_buffer_64.clearBit( 8, 16); + data_buffer_64.insertFromRight(&l_rcd_cntl_word_6_7, 24, 8); + data_buffer_64.insertFromRight(&l_rcd_cntl_word_8_9, 32, 8); + data_buffer_64.insertFromRight(&l_rcd_cntl_word_10, 40, 4); + data_buffer_64.insertFromRight(&l_rcd_cntl_word_11, 44, 4); + data_buffer_64.insertFromRight(&l_rcd_cntl_word_12, 48, 4); + data_buffer_64.insertFromRight(&l_rcd_cntl_word_13, 52, 4); + data_buffer_64.insertFromRight(&l_rcd_cntl_word_14, 56, 4); + data_buffer_64.insertFromRight(&l_rcd_cntl_word_15, 60, 4); + l_rcd_cntl_word_0_15 = data_buffer_64.getDoubleWord(0); if(rc) return rc; + FAPI_INF("from data buffer: rcd control word 0-15 %llX", l_rcd_cntl_word_0_15 ); + l_attr_eff_dimm_rcd_cntl_word_0_15[l_port][l_dimm] = l_attr_eff_dimm_rcd_cntl_word_0_15[l_port][l_dimm] & l_rcd_cntl_word_2_5_mask; + l_attr_eff_dimm_rcd_cntl_word_0_15[l_port][l_dimm] = l_attr_eff_dimm_rcd_cntl_word_0_15[l_port][l_dimm] | l_rcd_cntl_word_0_15; + + FAPI_INF("after mask: rcd control word 0-15 %.16llX", l_attr_eff_dimm_rcd_cntl_word_0_15[l_port][l_dimm] ); + + // Setup LRDIMM drive impedance, rtt nom, rtt wr, odt wr + l_dram_ron[l_port][l_dimm] = l_lrdimm_mr12_u8array[l_port][l_dimm] & 0x03; // Pulled from SPD LR MR1,2 DRAM DriverImpedance [1:0] + l_dram_rtt_nom[l_port][l_dimm] = (l_lrdimm_mr12_u8array[l_port][l_dimm] & 0x1C) >> 2; // Pulled from SPD LR MR1,2 DRAM RTT_nom for ranks 0/1 [4:2] + l_dram_rtt_wr[l_port][l_dimm] = (l_lrdimm_mr12_u8array[l_port][l_dimm] & 0xC0) >> 6; // Pulled from SPD LR MR1,2 DRAM RTT_WR [7:6] + + if ( l_dram_ron[l_port][l_dimm] == 0 ) { + l_dram_ron[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RON_OHM40; + } else if ( l_dram_ron[l_port][l_dimm] == 1 ) { + l_dram_ron[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RON_OHM34; + } else { + FAPI_ERR("Invalid SPD LR MR1,2 DRAM drv imp on %s!", i_target_mba.toEcmdString()); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); return rc; + } + + attr_eff_dram_ron[l_port][l_dimm] = l_dram_ron[l_port][l_dimm]; + FAPI_INF("Set LRDIMM DRAM_RON to SPD LR MR1,2 DRAM drv imp"); + + switch (l_dram_rtt_nom[l_port][l_dimm]) { + case 0 : l_dram_rtt_nom[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RTT_NOM_DISABLE; + break; + case 1 : l_dram_rtt_nom[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM60; + break; + case 2 : l_dram_rtt_nom[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM120; + break; + case 3 : l_dram_rtt_nom[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM40; + break; + case 4 : l_dram_rtt_nom[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM20; + break; + case 5 : l_dram_rtt_nom[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RTT_NOM_OHM30; + break; + default: FAPI_ERR("Invalid SPD LR MR1,2 DRAM RTT_NOM on %s!", i_target_mba.toEcmdString()); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); return rc; + break; + } + + switch (l_dram_rtt_wr[l_port][l_dimm]) { + case 0 : l_dram_rtt_wr[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RTT_WR_DISABLE; + break; + case 1 : l_dram_rtt_wr[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RTT_WR_OHM60; + break; + case 2 : l_dram_rtt_wr[l_port][l_dimm] = fapi::ENUM_ATTR_EFF_DRAM_RTT_WR_OHM120; + break; + default: FAPI_ERR("Invalid SPD LR MR1,2 DRAM RTT_WR on %s!", i_target_mba.toEcmdString()); + FAPI_SET_HWP_ERROR(rc, RC_MSS_PLACE_HOLDER_ERROR); return rc; + break; + } + + uint8_t l_rank; + for ( l_rank = 0; l_rank < RANK_SIZE; l_rank++ ) { // clear RTT_NOM & RTT_WR + attr_eff_dram_rtt_nom[l_port][l_dimm][l_rank] = fapi::ENUM_ATTR_EFF_DRAM_RTT_NOM_DISABLE; + attr_eff_dram_rtt_wr[l_port][l_dimm][l_rank] = fapi::ENUM_ATTR_EFF_DRAM_RTT_WR_DISABLE; + } + + if ( l_num_ranks_per_dimm_u8array[l_port][l_dimm] > 0 ) { // Set RTT_NOM Rank 0 for multi rank LRDIMM + attr_eff_dram_rtt_nom[l_port][l_dimm][0] = l_dram_rtt_nom[l_port][l_dimm]; // set attr_eff_dram_rtt_nom[0][0][0] + attr_eff_dram_rtt_wr[l_port][l_dimm][0] = l_dram_rtt_wr[l_port][l_dimm]; // set attr_eff_dram_rtt_wr[0][0][0] + + FAPI_INF("Setting Port0 Rank 0 LRDIMM RTT_NOM & RTT_WR from SPD LR MR1,2"); + + if ( l_num_ranks_per_dimm_u8array[l_port][l_dimm] > 1 ) { // Set RTT_NOM Rank 1 for 4rank or 8rank LRDIMM + attr_eff_dram_rtt_nom[l_port][l_dimm][1] = l_dram_rtt_nom[l_port][l_dimm]; // set attr_eff_dram_rtt_nom[0][0][1] + attr_eff_dram_rtt_wr[l_port][l_dimm][1] = l_dram_rtt_wr[l_port][l_dimm]; // set attr_eff_dram_rtt_wr[0][0][1] + + attr_eff_dram_rtt_wr[l_port][l_dimm][2] = l_dram_rtt_wr[l_port][l_dimm]; // set attr_eff_dram_rtt_wr[0][0][2] + attr_eff_dram_rtt_wr[l_port][l_dimm][3] = l_dram_rtt_wr[l_port][l_dimm]; // set attr_eff_dram_rtt_wr[0][0][3] + FAPI_INF("Setting Port0 Rank 1+ LRDIMM RTT_NOM & RTT_WR from SPD LR MR1,2"); + } + } + +//------------------------------------------------------------------------------------------------------------- + + // Set ODT_WR for each valid rank as single RDIMM rank value. + if ( l_num_ranks_per_dimm_u8array[l_port][l_dimm] > 1 ) { // SET ODT_WR Rank 1 for multi rank LRDIMM (8R or 4R) + attr_eff_odt_wr[l_port][l_dimm][1] = attr_eff_odt_wr[l_port][l_dimm][0]; // set attr_eff_odt_wr[0][0][1] to attr_eff_odt_wr[0][0][0] + if ( l_num_ranks_per_dimm_u8array[l_port][l_dimm] == 4 ) { // Set ODT_WR Rankd 2,3 for 4 rank LRDIMM + attr_eff_odt_wr[l_port][l_dimm][2] = attr_eff_odt_wr[l_port][l_dimm][0]; // set attr_eff_odt_wr[0][0][2] to attr_eff_odt_wr[0][0][0] + attr_eff_odt_wr[l_port][l_dimm][3] = attr_eff_odt_wr[l_port][l_dimm][0]; // set attr_eff_odt_wr[0][0][3] to attr_eff_odt_wr[0][0][0] + } + } + + } // end dimm loop + } // end port loop + + // Set adjusted attributes + rc = FAPI_ATTR_SET(ATTR_EFF_DRAM_RON, &i_target_mba, attr_eff_dram_ron); if(rc) return rc; + rc = FAPI_ATTR_SET(ATTR_EFF_DRAM_RTT_NOM, &i_target_mba, attr_eff_dram_rtt_nom); if(rc) return rc; + rc = FAPI_ATTR_SET(ATTR_EFF_DRAM_RTT_WR, &i_target_mba, attr_eff_dram_rtt_wr); if(rc) return rc; + rc = FAPI_ATTR_SET(ATTR_EFF_ODT_WR, &i_target_mba, attr_eff_odt_wr); if(rc) return rc; + + rc = FAPI_ATTR_SET(ATTR_EFF_DIMM_RCD_CNTL_WORD_0_15, &i_target_mba, l_attr_eff_dimm_rcd_cntl_word_0_15); if(rc) return rc; + + return rc; +} + +fapi::ReturnCode mss_spec_rcd_load( Target& i_target, uint32_t i_port_number, uint8_t *p_i_rcd_num_arr, uint8_t i_rcd_num_arr_length, uint64_t i_rcd_word[], uint32_t& io_ccs_inst_cnt,uint8_t i_keep_cke_high) +{ + const uint8_t MAX_NUM_PORTS=2; + const uint8_t MAX_NUM_DIMMS=2; + ReturnCode rc; + ReturnCode rc_buff; + uint32_t rc_num = 0; + uint32_t dimm_number; + uint8_t spec_rcd; + + ecmdDataBufferBase rcd_cntl_wrd_4(8); + ecmdDataBufferBase rcd_cntl_wrd_64(64); + uint16_t num_ranks; + + uint16_t num_idles_delay = 20; // default=12 klc + + ecmdDataBufferBase address_16(16); + ecmdDataBufferBase bank_3(3); + ecmdDataBufferBase activate_1(1); + ecmdDataBufferBase rasn_1(1); + rc_num = rc_num | rasn_1.setBit(0); + ecmdDataBufferBase casn_1(1); + rc_num = rc_num | casn_1.setBit(0); + ecmdDataBufferBase wen_1(1); + rc_num = rc_num | wen_1.setBit(0); + ecmdDataBufferBase cke_4(4); + if (i_keep_cke_high == 1) + rc_num = rc_num | cke_4.setBit(0,4); + else + rc_num = rc_num | cke_4.clearBit(0,4); + ecmdDataBufferBase csn_8(8); + rc_num = rc_num | csn_8.setBit(0,8); + ecmdDataBufferBase odt_4(4); + rc_num = rc_num | odt_4.setBit(0,4); + ecmdDataBufferBase ddr_cal_type_4(4); + + ecmdDataBufferBase num_idles_16(16); + ecmdDataBufferBase num_repeat_16(16); + ecmdDataBufferBase data_20(20); + ecmdDataBufferBase read_compare_1(1); + ecmdDataBufferBase rank_cal_4(4); + ecmdDataBufferBase ddr_cal_enable_1(1); + ecmdDataBufferBase ccs_end_1(1); + + uint8_t num_ranks_array[MAX_NUM_PORTS][MAX_NUM_DIMMS]; //[port][dimm] + + rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target, num_ranks_array); + if(rc) return rc; + + FAPI_INF( "+++++++++++++++++++++ LOADING RCD CONTROL WORD FOR PORT %d +++++++++++++++++++++", i_port_number); + + for ( dimm_number = 0; dimm_number < MAX_NUM_DIMMS; dimm_number++) + { + num_ranks = num_ranks_array[i_port_number][dimm_number]; + + if (num_ranks == 0) + { + FAPI_INF( "PORT%d DIMM%d not configured. Num_ranks: %d", i_port_number, dimm_number, num_ranks); + } + else + { + FAPI_INF( "RCD SETTINGS FOR PORT%d DIMM%d ", i_port_number, dimm_number); + FAPI_INF( "RCD Control Word: 0x%016llX", i_rcd_word[dimm_number]); + FAPI_INF( "Loading function specific RCD Control Words"); + + if (rc_num) + { + FAPI_ERR( "mss_spec_rcd_load: Error setting up buffers"); + rc_buff.setEcmdError(rc_num); + return rc_buff; + } + + rc_num = rc_num | csn_8.setBit(0,8); // reset CS lines + // for dimm0 use CS0,1 (active low); for dimm1 use CS4,5 (active low) + rc_num = rc_num | csn_8.clearBit( (dimm_number * 4), 2 ); + // set specific control words + for ( spec_rcd = 0; spec_rcd < i_rcd_num_arr_length; spec_rcd++ ) + { + rc_num = rc_num | bank_3.clearBit(0, 3); + rc_num = rc_num | address_16.clearBit(0, 16); + + rc_num = rc_num | rcd_cntl_wrd_64.setDoubleWord(0, i_rcd_word[dimm_number]); + rc_num = rc_num | rcd_cntl_wrd_64.extract(rcd_cntl_wrd_4, 4*p_i_rcd_num_arr[spec_rcd], 4); + + //control word number code bits A0, A1, A2, BA2 + rc_num = rc_num | bank_3.insert(p_i_rcd_num_arr[spec_rcd], 2, 1, 4); // BA2(MSB) from array bit 4 + rc_num = rc_num | address_16.insert(p_i_rcd_num_arr[spec_rcd], 2, 1, 5); // A2 + rc_num = rc_num | address_16.insert(p_i_rcd_num_arr[spec_rcd], 1, 1, 6); // A1 + rc_num = rc_num | address_16.insert(p_i_rcd_num_arr[spec_rcd], 0, 1, 7); // A0 + + //control word values RCD0 = A3, RCD1 = A4, RCD2 = BA0, RCD3 = BA1 + rc_num = rc_num | bank_3.insert(rcd_cntl_wrd_4, 1, 1, 0); // BA1 (MSB) + rc_num = rc_num | bank_3.insert(rcd_cntl_wrd_4, 0, 1, 1); // BA0 + rc_num = rc_num | address_16.insert(rcd_cntl_wrd_4, 4, 1, 2); // A4 + rc_num = rc_num | address_16.insert(rcd_cntl_wrd_4, 3, 1, 3); // A3 + + FAPI_INF("Loading RCD %d (0x%02x) = 0x%01X", p_i_rcd_num_arr[spec_rcd], + p_i_rcd_num_arr[spec_rcd], + (rcd_cntl_wrd_4.getByte(0)>>4)); + + // Send out to the CCS array + rc_num = rc_num | num_idles_16.insertFromRight((uint32_t) num_idles_delay, 0, 16); + rc = mss_ccs_inst_arry_0( i_target, + io_ccs_inst_cnt, + address_16, + bank_3, + activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + ddr_cal_type_4, + i_port_number); + if(rc) return rc; + rc = mss_ccs_inst_arry_1( i_target, + io_ccs_inst_cnt, + num_idles_16, + num_repeat_16, + data_20, + read_compare_1, + rank_cal_4, + ddr_cal_enable_1, + ccs_end_1); + if(rc) return rc; + io_ccs_inst_cnt ++; + + if (rc_num) + { + FAPI_ERR( "mss_rcd_load: Error setting up buffers"); + rc_buff.setEcmdError(rc_num); + return rc_buff; + } + } //end control word loop + } // end valid rank + } // end dimm loop + return rc; +} + +#endif |