From bdf069fd13603c3ba43d7831df25fcb6f5b81c4a Mon Sep 17 00:00:00 2001 From: Louis Stermole Date: Tue, 3 Jul 2018 14:17:13 -0500 Subject: Add soft PPR (row repair) function for p9c Change-Id: I728a494f91f1f460c0700bbeeca47a0e5739622f CQ:SW444976 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/61829 Tested-by: Jenkins Server Reviewed-by: STEPHEN GLANCY Tested-by: Hostboot CI Reviewed-by: ANDRE A. MARIN Reviewed-by: Jennifer A. Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/61896 Reviewed-by: Daniel M. Crowell Tested-by: Daniel M. Crowell --- .../procedures/hwp/memory/p9c_mss_ddr4_funcs.C | 123 ++++ .../procedures/hwp/memory/p9c_mss_ddr4_funcs.H | 12 + .../centaur/procedures/hwp/memory/p9c_mss_funcs.C | 713 ++++++++++++++++++++- .../centaur/procedures/hwp/memory/p9c_mss_funcs.H | 77 ++- .../procedures/hwp/memory/p9c_mss_row_repair.C | 215 +++++++ .../procedures/hwp/memory/p9c_mss_row_repair.H | 36 ++ .../procedures/hwp/memory/p9c_mss_row_repair.mk | 7 + .../xml/error_info/p9c_mss_funcs_errors.xml | 13 + 8 files changed, 1189 insertions(+), 7 deletions(-) (limited to 'src/import/chips/centaur') diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_funcs.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_funcs.C index ccb9b195c..1ed21be5d 100755 --- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_funcs.C +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_funcs.C @@ -4781,3 +4781,126 @@ fapi2::ReturnCode mss_ddr4_load_nominal_mrs_pda(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + uint32_t& io_instruction_number) +{ + uint8_t l_is_sim = 0; + uint8_t l_address_mirror_map[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; //address_mirror_map[port][dimm] + uint8_t l_stack_type_u8array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; + const uint8_t l_dimm = i_addr.mrank / MAX_RANKS_PER_DIMM; + const uint8_t l_dimm_rank = i_addr.mrank % MAX_RANKS_PER_DIMM; + + // CCS Array 0 buffers + fapi2::variable_buffer addr_16(16); + fapi2::variable_buffer bank_3(3); + fapi2::variable_buffer ddr4_activate_1(1); + fapi2::variable_buffer rasn_1(1); + fapi2::variable_buffer casn_1(1); + fapi2::variable_buffer wen_1(1); + fapi2::variable_buffer cke_4(4); + fapi2::variable_buffer csn_8(8); + fapi2::variable_buffer odt_4(4); + fapi2::variable_buffer cal_type_4(4); + + // CCS Array 1 buffers + fapi2::variable_buffer idles_16(16); + fapi2::variable_buffer repeat_16(16); + fapi2::variable_buffer pattern_20(20); + fapi2::variable_buffer read_compare_1(1); + fapi2::variable_buffer rank_cal_4(4); + fapi2::variable_buffer cal_enable_1(1); + fapi2::variable_buffer ccs_end_1(1); + fapi2::buffer l_data_8; + fapi2::buffer l_data_16; + uint32_t l_port = i_addr.port; + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target(), l_is_sim)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_ADDRESS_MIRRORING, i_target_mba, l_address_mirror_map)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target_mba, l_stack_type_u8array)); + + // CCS Array 0 Setup + + // Buffer conversions from inputs + FAPI_TRY(addr_16.insertFromRight(i_addr.row_addr, 0, 16)); + FAPI_TRY(addr_16.extract(l_data_16)); + l_data_16.reverse(); + FAPI_TRY(addr_16.insert((uint16_t)l_data_16)); + FAPI_TRY(bank_3.insertFromRight(i_addr.bank, 0, 3)); + FAPI_TRY(bank_3.extract(l_data_8, 0, 3)); + l_data_8.reverse(); + FAPI_TRY(bank_3.insertFromRight((uint8_t)l_data_8, 0 , 3)); + FAPI_INF("%s add_MRS_to_ccs ADDR : 0x%04X MR : 0x%X", mss::c_str(i_target_mba), i_addr.row_addr, i_addr.bank); + + FAPI_TRY(cs_decode(i_target_mba, i_addr, l_stack_type_u8array[0][0], csn_8)); + + // Command structure setup + cke_4.flush<1>(); + FAPI_TRY(rasn_1.clearBit(0)); + FAPI_TRY(casn_1.clearBit(0)); + FAPI_TRY(wen_1.clearBit(0)); + + FAPI_TRY(read_compare_1.clearBit(0)); + + // Final setup + odt_4.flush<0>(); + cal_type_4.flush<0>(); + FAPI_TRY(ddr4_activate_1.setBit(0)); + + if ((l_address_mirror_map[l_port][l_dimm] & (0x08 >> l_dimm_rank) ) && (l_is_sim == 0)) + { + FAPI_TRY(mss_address_mirror_swizzle(i_target_mba, addr_16, bank_3)); + } + + FAPI_TRY(mss_ccs_inst_arry_0(i_target_mba, + io_instruction_number, + addr_16, + bank_3, + ddr4_activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + cal_type_4, + l_port)); + + // CCS Array 1 Setup + FAPI_TRY(idles_16.insertFromRight(i_delay, 0, 16)); + repeat_16.flush<0>(); + pattern_20.flush<0>(); + read_compare_1.flush<0>(); + rank_cal_4.flush<0>(); + cal_enable_1.flush<0>(); + ccs_end_1.flush<0>(); + + FAPI_TRY(mss_ccs_inst_arry_1(i_target_mba, + io_instruction_number, + idles_16, + repeat_16, + pattern_20, + read_compare_1, + rank_cal_4, + cal_enable_1, + ccs_end_1)); + ++io_instruction_number; + + // Do a B side MRS write + FAPI_TRY( setup_b_side_ccs(i_target_mba, l_port, i_addr.mrank, addr_16, + bank_3, ddr4_activate_1, rasn_1, casn_1, wen_1, + cke_4, odt_4, cal_type_4, idles_16, repeat_16, + pattern_20, read_compare_1, rank_cal_4, cal_enable_1, + ccs_end_1, io_instruction_number) ); + +fapi_try_exit: + return fapi2::current_err; +} diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_funcs.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_funcs.H index eb20a97fd..56525f340 100755 --- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_funcs.H +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_funcs.H @@ -35,6 +35,7 @@ #ifndef _MSS_DDR4_FUNCS_H #define _MSS_DDR4_FUNCS_H +#include //---------------------------------------------------------------------- // DDR4 FUNCS @@ -212,6 +213,17 @@ fapi2::ReturnCode setup_b_side_ccs(const fapi2::Target& const fapi2::variable_buffer& i_ccs_end_1, uint32_t& io_ccs_inst_cnt); +/// @brief Add an MRS command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for MRS +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert MRS command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_mrs_to_ccs_ddr4(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + uint32_t& io_instruction_number); + #endif /* _MSS_DDR4_FUNCS_H */ diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_funcs.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_funcs.C index 716d31e7b..657366923 100755 --- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_funcs.C +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_funcs.C @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -2456,6 +2457,603 @@ fapi2::ReturnCode add_nop_to_ccs(const fapi2::Target& i_ cal_type_4, l_port)); + // CCS Array 1 Setup + FAPI_TRY(idles_16.insertFromRight(i_delay, 0, 16)); + repeat_16.flush<0>(); + pattern_20.flush<0>(); + read_compare_1.flush<0>(); + rank_cal_4.flush<0>(); + cal_enable_1.flush<0>(); + ccs_end_1.flush<0>(); + + FAPI_TRY(mss_ccs_inst_arry_1(i_target_mba, + io_instruction_number, + idles_16, + repeat_16, + pattern_20, + read_compare_1, + rank_cal_4, + cal_enable_1, + ccs_end_1)); + ++io_instruction_number; + +fapi_try_exit: + return fapi2::current_err; +} + +/// @brief Add an MRS command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for MRS +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert MRS command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_mrs_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + uint32_t& io_instruction_number) +{ + uint8_t l_is_sim = 0; + uint8_t l_address_mirror_map[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; //address_mirror_map[port][dimm] + uint8_t l_stack_type_u8array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; + const uint8_t l_dimm = i_addr.mrank / MAX_RANKS_PER_DIMM; + const uint8_t l_dimm_rank = i_addr.mrank - MAX_RANKS_PER_DIMM * l_dimm; + + // CCS Array 0 buffers + fapi2::variable_buffer addr_16(16); + fapi2::variable_buffer bank_3(3); + fapi2::variable_buffer ddr4_activate_1(1); + fapi2::variable_buffer rasn_1(1); + fapi2::variable_buffer casn_1(1); + fapi2::variable_buffer wen_1(1); + fapi2::variable_buffer cke_4(4); + fapi2::variable_buffer csn_8(8); + fapi2::variable_buffer odt_4(4); + fapi2::variable_buffer cal_type_4(4); + + // CCS Array 1 buffers + fapi2::variable_buffer idles_16(16); + fapi2::variable_buffer repeat_16(16); + fapi2::variable_buffer pattern_20(20); + fapi2::variable_buffer read_compare_1(1); + fapi2::variable_buffer rank_cal_4(4); + fapi2::variable_buffer cal_enable_1(1); + fapi2::variable_buffer ccs_end_1(1); + fapi2::buffer l_data_8; + fapi2::buffer l_data_16; + uint32_t l_port = i_addr.port; + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target(), l_is_sim)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_ADDRESS_MIRRORING, i_target_mba, l_address_mirror_map)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target_mba, l_stack_type_u8array)); + + // CCS Array 0 Setup + + // Buffer conversions from inputs + FAPI_TRY(addr_16.insertFromRight(i_addr.row_addr, 0, 16)); + FAPI_TRY(addr_16.extract(l_data_16)); + l_data_16.reverse(); + FAPI_TRY(addr_16.insert((uint16_t)l_data_16)); + FAPI_TRY(bank_3.insertFromRight(i_addr.bank, 0, 3)); + FAPI_TRY(bank_3.extract(l_data_8, 0, 3)); + l_data_8.reverse(); + FAPI_TRY(bank_3.insertFromRight((uint8_t)l_data_8, 0 , 3)); + FAPI_INF("%s add_MRS_to_ccs ADDR : 0x%04X MR : 0x%X", mss::c_str(i_target_mba), i_addr.row_addr, i_addr.bank); + + FAPI_TRY(cs_decode(i_target_mba, i_addr, l_stack_type_u8array[0][0], csn_8)); + + // Command structure setup + cke_4.flush<1>(); + FAPI_TRY(rasn_1.clearBit(0)); + FAPI_TRY(casn_1.clearBit(0)); + FAPI_TRY(wen_1.clearBit(0)); + + FAPI_TRY(read_compare_1.clearBit(0)); + + // Final setup + odt_4.flush<0>(); + cal_type_4.flush<0>(); + FAPI_TRY(ddr4_activate_1.setBit(0)); + + if ((l_address_mirror_map[l_port][l_dimm] & (0x08 >> l_dimm_rank) ) && (l_is_sim == 0)) + { + FAPI_TRY(mss_address_mirror_swizzle(i_target_mba, addr_16, bank_3)); + } + + FAPI_TRY(mss_ccs_inst_arry_0(i_target_mba, + io_instruction_number, + addr_16, + bank_3, + ddr4_activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + cal_type_4, + l_port)); + + // CCS Array 1 Setup + FAPI_TRY(idles_16.insertFromRight(i_delay, 0, 16)); + repeat_16.flush<0>(); + pattern_20.flush<0>(); + read_compare_1.flush<0>(); + rank_cal_4.flush<0>(); + cal_enable_1.flush<0>(); + ccs_end_1.flush<0>(); + + FAPI_TRY(mss_ccs_inst_arry_1(i_target_mba, + io_instruction_number, + idles_16, + repeat_16, + pattern_20, + read_compare_1, + rank_cal_4, + cal_enable_1, + ccs_end_1)); + ++io_instruction_number; + +fapi_try_exit: + return fapi2::current_err; +} + +/// @brief Add an ACT command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_activate_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + uint32_t& io_instruction_number) +{ + uint8_t l_is_sim = 0; + uint8_t l_address_mirror_map[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; //address_mirror_map[port][dimm] + uint8_t l_stack_type_u8array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; + const uint8_t l_dimm = i_addr.mrank / MAX_RANKS_PER_DIMM; + const uint8_t l_dimm_rank = i_addr.mrank - MAX_RANKS_PER_DIMM * l_dimm; + + // CCS Array 0 buffers + fapi2::variable_buffer addr_16(16); + fapi2::variable_buffer bank_3(3); + fapi2::variable_buffer ddr4_activate_1(1); + fapi2::variable_buffer rasn_1(1); + fapi2::variable_buffer casn_1(1); + fapi2::variable_buffer wen_1(1); + fapi2::variable_buffer cke_4(4); + fapi2::variable_buffer csn_8(8); + fapi2::variable_buffer odt_4(4); + fapi2::variable_buffer cal_type_4(4); + + // CCS Array 1 buffers + fapi2::variable_buffer idles_16(16); + fapi2::variable_buffer repeat_16(16); + fapi2::variable_buffer pattern_20(20); + fapi2::variable_buffer read_compare_1(1); + fapi2::variable_buffer rank_cal_4(4); + fapi2::variable_buffer cal_enable_1(1); + fapi2::variable_buffer ccs_end_1(1); + + uint8_t l_dram_type; + uint32_t l_port = i_addr.port; + fapi2::buffer l_data_8; + fapi2::buffer l_data_16; + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target(), l_is_sim)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_ADDRESS_MIRRORING, i_target_mba, l_address_mirror_map)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba, l_dram_type)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target_mba, l_stack_type_u8array)); + + // CCS Array 0 Setup + + // Buffer conversions from inputs + FAPI_TRY(bank_3.insertFromRight(i_addr.bank, 0, 3)); + FAPI_TRY(bank_3.extract(l_data_8, 0, 3)); + l_data_8.reverse(); + FAPI_TRY(bank_3.insertFromRight((uint8_t)l_data_8, 0 , 3)); + csn_8.flush<1>(); + cke_4.flush<1>(); + + FAPI_TRY(cs_decode(i_target_mba, i_addr, l_stack_type_u8array[0][0], csn_8)); + + // Command structure setup + // executes DDR4 commands if neccessary, otherwise executes DDR3 commands + if(l_dram_type == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) + { + FAPI_TRY(ddr4_activate_1.clearBit(0)); + + FAPI_TRY(wen_1.insert(i_addr.row_addr, 0 , 1 , 17)); + FAPI_TRY(casn_1.insert(i_addr.row_addr, 0 , 1 , 16)); + FAPI_TRY(rasn_1.insert(i_addr.row_addr, 0 , 1 , 15)); + + FAPI_TRY(addr_16.insertFromRight(i_addr.row_addr, 0, 16)); + FAPI_TRY(addr_16.extract(l_data_16)); + l_data_16.reverse(); + FAPI_TRY(addr_16.insert((uint16_t)l_data_16)); + + FAPI_TRY(addr_16.insert(i_addr.row_addr, 14 , 1 , 14)); + FAPI_TRY(addr_16.insert(i_addr.bank, 15 , 1 , 4)); + } + else + { + FAPI_TRY(rasn_1.clearBit(0)); + FAPI_TRY(casn_1.setBit(0)); + FAPI_TRY(ddr4_activate_1.setBit(0)); + FAPI_TRY(addr_16.insertFromRight(i_addr.row_addr, 0, 16)); + FAPI_TRY(addr_16.extract(l_data_16)); + l_data_16.reverse(); + FAPI_TRY(addr_16.insert((uint16_t)l_data_16)); + } + + // Final setup + odt_4.flush<0>(); + cal_type_4.flush<0>(); + + if ((l_address_mirror_map[l_port][l_dimm] & (0x08 >> l_dimm_rank) ) && (l_is_sim == 0)) + { + FAPI_TRY(mss_address_mirror_swizzle(i_target_mba, addr_16, bank_3)); + } + + FAPI_TRY(mss_ccs_inst_arry_0(i_target_mba, + io_instruction_number, + addr_16, + bank_3, + ddr4_activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + cal_type_4, + l_port)); + + // CCS Array 1 Setup + FAPI_TRY(idles_16.insertFromRight(i_delay, 0, 16)); + repeat_16.flush<0>(); + pattern_20.flush<0>(); + read_compare_1.flush<0>(); + rank_cal_4.flush<0>(); + cal_enable_1.flush<0>(); + ccs_end_1.flush<0>(); + + FAPI_TRY(mss_ccs_inst_arry_1(i_target_mba, + io_instruction_number, + idles_16, + repeat_16, + pattern_20, + read_compare_1, + rank_cal_4, + cal_enable_1, + ccs_end_1)); + ++io_instruction_number; + +fapi_try_exit: + return fapi2::current_err; +} + +/// @brief Add a WR command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_write_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + uint32_t& io_instruction_number) +{ + uint8_t l_is_sim = 0; + uint8_t l_address_mirror_map[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; //address_mirror_map[port][dimm] + uint8_t l_stack_type_u8array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; + const uint8_t l_dimm = i_addr.mrank / MAX_RANKS_PER_DIMM; + const uint8_t l_dimm_rank = i_addr.mrank - MAX_RANKS_PER_DIMM * l_dimm; + + // CCS Array 0 buffers + fapi2::variable_buffer addr_16(16); + fapi2::variable_buffer bank_3(3); + fapi2::variable_buffer ddr4_activate_1(1); + fapi2::variable_buffer rasn_1(1); + fapi2::variable_buffer casn_1(1); + fapi2::variable_buffer wen_1(1); + fapi2::variable_buffer cke_4(4); + fapi2::variable_buffer csn_8(8); + fapi2::variable_buffer odt_4(4); + fapi2::variable_buffer cal_type_4(4); + + // CCS Array 1 buffers + fapi2::variable_buffer idles_16(16); + fapi2::variable_buffer repeat_16(16); + fapi2::variable_buffer pattern_20(20); + fapi2::variable_buffer read_compare_1(1); + fapi2::variable_buffer rank_cal_4(4); + fapi2::variable_buffer cal_enable_1(1); + fapi2::variable_buffer ccs_end_1(1); + + uint8_t l_dram_type; + uint8_t l_odt[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM]; + uint32_t l_port = i_addr.port; + fapi2::buffer l_data_8; + fapi2::buffer l_data_16; + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target(), l_is_sim)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_ADDRESS_MIRRORING, i_target_mba, l_address_mirror_map)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba, l_dram_type)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_ODT_WR, i_target_mba, l_odt)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target_mba, l_stack_type_u8array)); + + // Buffer conversions from inputs + FAPI_TRY(bank_3.insertFromRight(i_addr.bank, 0, 3)); + FAPI_TRY(bank_3.extract(l_data_8, 0, 3)); + l_data_8.reverse(); + FAPI_TRY(bank_3.insertFromRight((uint8_t)l_data_8, 0 , 3)); + + FAPI_TRY(cs_decode(i_target_mba, i_addr, l_stack_type_u8array[0][0], csn_8)); + + // Command structure setup + cke_4.flush<1>(); + FAPI_TRY(rasn_1.setBit(0)); + FAPI_TRY(casn_1.clearBit(0)); + FAPI_TRY(wen_1.clearBit(0)); + + // Final setup + FAPI_TRY(odt_4.insert(l_odt[l_port][l_dimm][l_dimm_rank], 0, 4)); + cal_type_4.flush<0>(); + FAPI_TRY(ddr4_activate_1.setBit(0)); + + if(l_dram_type == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) + { + FAPI_TRY(addr_16.insertFromRight(i_addr.col_addr, 0, 16)); + FAPI_TRY(addr_16.extract(l_data_16)); + l_data_16.reverse(); + FAPI_TRY(addr_16.insert((uint16_t)l_data_16)); + FAPI_TRY(addr_16.setBit(12)); // burst length 8 + + FAPI_TRY(addr_16.insert(i_addr.bank, 15 , 1 , 4)); + + } + else + { + FAPI_TRY(addr_16.insertFromRight(i_addr.col_addr, 0, 16)); + FAPI_TRY(addr_16.extract(l_data_16)); + l_data_16.reverse(); + FAPI_TRY(addr_16.insert((uint16_t)l_data_16)); + FAPI_TRY(addr_16.setBit(12)); // burst length 8 + } + + if ((l_address_mirror_map[l_port][l_dimm] & (0x08 >> l_dimm_rank) ) && (l_is_sim == 0)) + { + FAPI_TRY(mss_address_mirror_swizzle(i_target_mba, addr_16, bank_3)); + } + + FAPI_TRY(mss_ccs_inst_arry_0(i_target_mba, + io_instruction_number, + addr_16, + bank_3, + ddr4_activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + cal_type_4, + l_port)); + + // CCS Array 1 Setup + FAPI_TRY(idles_16.insertFromRight(i_delay, 0, 16)); + repeat_16.flush<0>(); + pattern_20.flush<0>(); + read_compare_1.flush<0>(); + rank_cal_4.flush<0>(); + cal_enable_1.flush<0>(); + ccs_end_1.flush<0>(); + + FAPI_TRY(mss_ccs_inst_arry_1(i_target_mba, + io_instruction_number, + idles_16, + repeat_16, + pattern_20, + read_compare_1, + rank_cal_4, + cal_enable_1, + ccs_end_1)); + ++io_instruction_number; + +fapi_try_exit: + return fapi2::current_err; +} + +/// @brief Add an ODT command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_repeat number of repeats to specify in this instruction +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_odt_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_repeat, + const uint32_t i_delay, + uint32_t& io_instruction_number) +{ + const uint8_t l_dimm = i_addr.mrank / MAX_RANKS_PER_DIMM; + const uint8_t l_dimm_rank = i_addr.mrank % MAX_RANKS_PER_DIMM; + + // CCS Array 0 buffers + fapi2::variable_buffer addr_16(16); + fapi2::variable_buffer bank_3(3); + fapi2::variable_buffer ddr4_activate_1(1); + fapi2::variable_buffer rasn_1(1); + fapi2::variable_buffer casn_1(1); + fapi2::variable_buffer wen_1(1); + fapi2::variable_buffer cke_4(4); + fapi2::variable_buffer csn_8(8); + fapi2::variable_buffer odt_4(4); + fapi2::variable_buffer cal_type_4(4); + + // CCS Array 1 buffers + fapi2::variable_buffer idles_16(16); + fapi2::variable_buffer repeat_16(16); + fapi2::variable_buffer pattern_20(20); + fapi2::variable_buffer read_compare_1(1); + fapi2::variable_buffer rank_cal_4(4); + fapi2::variable_buffer cal_enable_1(1); + fapi2::variable_buffer ccs_end_1(1); + + uint8_t l_dram_type; + uint8_t l_odt[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM]; + const uint32_t odt_cyc = 5; + uint32_t l_port = i_addr.port; + fapi2::buffer l_data_8; + fapi2::buffer l_data_16; + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba, l_dram_type)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_ODT_WR, i_target_mba, l_odt)); + + // Buffer conversions from inputs + addr_16.flush<0>(); + bank_3.flush<0>(); + csn_8.flush<1>(); + FAPI_TRY(csn_8.clearBit(6)); + FAPI_TRY(csn_8.clearBit(7)); // need to have a unused cs_n for the valid data to write out on the bus. + + // Command structure setup + cke_4.flush<1>(); + FAPI_TRY(rasn_1.setBit(0)); + FAPI_TRY(casn_1.setBit(0)); + FAPI_TRY(wen_1.setBit(0)); + + // Final setup + FAPI_TRY(odt_4.insert(l_odt[l_port][l_dimm][l_dimm_rank], 0, 4)); + cal_type_4.flush<0>(); + FAPI_TRY(ddr4_activate_1.setBit(0)); + + if(l_dram_type == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) + { + FAPI_TRY(addr_16.setBit(12)); // burst length 8 + } + + FAPI_TRY(mss_ccs_inst_arry_0(i_target_mba, + io_instruction_number, + addr_16, + bank_3, + ddr4_activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + cal_type_4, + l_port)); + + // CCS Array 1 Setup + FAPI_TRY(idles_16.insertFromRight(i_delay, 0, 16)); + repeat_16.flush<0>(); + FAPI_TRY(repeat_16.insertFromRight((i_repeat + odt_cyc), 0, 16)); + pattern_20.flush<0>(); + read_compare_1.flush<0>(); + rank_cal_4.flush<0>(); + cal_enable_1.flush<0>(); + ccs_end_1.flush<0>(); + + FAPI_TRY(mss_ccs_inst_arry_1(i_target_mba, + io_instruction_number, + idles_16, + repeat_16, + pattern_20, + read_compare_1, + rank_cal_4, + cal_enable_1, + ccs_end_1)); + ++io_instruction_number; + +fapi_try_exit: + return fapi2::current_err; +} + +/// @brief Add a precharge all command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_delay delay associated with this instruction +/// @param[in] i_odt_wr value of ATTR_CEN_VPD_ODT_WR +/// @param[in] i_stack_type value of ATTR_CEN_EFF_STACK_TYPE +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_precharge_all_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + const uint8_t (&i_odt_wr)[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM], + const uint8_t (&i_stack_type)[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT], + uint32_t& io_instruction_number) +{ + const uint8_t l_dimm = i_addr.mrank / MAX_RANKS_PER_DIMM; + const uint8_t l_dimm_rank = i_addr.mrank % MAX_RANKS_PER_DIMM; + + // CCS Array 0 buffers + fapi2::variable_buffer addr_16(16); + fapi2::variable_buffer bank_3(3); + fapi2::variable_buffer ddr4_activate_1(1); + fapi2::variable_buffer rasn_1(1); + fapi2::variable_buffer casn_1(1); + fapi2::variable_buffer wen_1(1); + fapi2::variable_buffer cke_4(4); + fapi2::variable_buffer csn_8(8); + fapi2::variable_buffer odt_4(4); + fapi2::variable_buffer cal_type_4(4); + + // CCS Array 1 buffers + fapi2::variable_buffer idles_16(16); + fapi2::variable_buffer repeat_16(16); + fapi2::variable_buffer pattern_20(20); + fapi2::variable_buffer read_compare_1(1); + fapi2::variable_buffer rank_cal_4(4); + fapi2::variable_buffer cal_enable_1(1); + fapi2::variable_buffer ccs_end_1(1); + + uint32_t l_port = i_addr.port; + fapi2::buffer l_data_8; + fapi2::buffer l_data_16; + + // Buffer conversions from inputs + FAPI_TRY(addr_16.insertFromRight(i_addr.col_addr, 0, 16)); + FAPI_TRY(addr_16.extract(l_data_16)); + l_data_16.reverse(); + FAPI_TRY(addr_16.insert((uint16_t)l_data_16)); + FAPI_TRY(bank_3.insertFromRight(i_addr.bank, 0, 3)); + FAPI_TRY(bank_3.extract(l_data_8, 0, 3)); + l_data_8.reverse(); + FAPI_TRY(bank_3.insertFromRight((uint8_t)l_data_8, 0 , 3)); + + FAPI_TRY(cs_decode(i_target_mba, i_addr, i_stack_type[0][0], csn_8)); + + // Command structure setup + cke_4.flush<1>(); + FAPI_TRY(rasn_1.clearBit(0)); + FAPI_TRY(casn_1.setBit(0)); + FAPI_TRY(wen_1.clearBit(0)); + FAPI_TRY(addr_16.setBit(10)); + + // Final setup + FAPI_TRY(odt_4.insert(i_odt_wr[l_port][l_dimm][l_dimm_rank], 0, 4)); + cal_type_4.flush<0>(); + FAPI_TRY(ddr4_activate_1.setBit(0)); + + FAPI_TRY(mss_ccs_inst_arry_0(i_target_mba, + io_instruction_number, + addr_16, + bank_3, + ddr4_activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + cal_type_4, + l_port)); // CCS Array 1 Setup FAPI_TRY(idles_16.insertFromRight(i_delay, 0, 16)); @@ -2475,7 +3073,109 @@ fapi2::ReturnCode add_nop_to_ccs(const fapi2::Target& i_ rank_cal_4, cal_enable_1, ccs_end_1)); + ++io_instruction_number; + +fapi_try_exit: + return fapi2::current_err; +} + +/// @brief Add a DES command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_repeat number of repeats to specify in this instruction +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_des_with_repeat_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_repeat, + const uint32_t i_delay, + uint32_t& io_instruction_number) +{ + // CCS Array 0 buffers + fapi2::variable_buffer addr_16(16); + fapi2::variable_buffer bank_3(3); + fapi2::variable_buffer ddr4_activate_1(1); + fapi2::variable_buffer rasn_1(1); + fapi2::variable_buffer casn_1(1); + fapi2::variable_buffer wen_1(1); + fapi2::variable_buffer cke_4(4); + fapi2::variable_buffer csn_8(8); + fapi2::variable_buffer odt_4(4); + fapi2::variable_buffer cal_type_4(4); + + // CCS Array 1 buffers + fapi2::variable_buffer idles_16(16); + fapi2::variable_buffer repeat_16(16); + fapi2::variable_buffer pattern_20(20); + fapi2::variable_buffer read_compare_1(1); + fapi2::variable_buffer rank_cal_4(4); + fapi2::variable_buffer cal_enable_1(1); + fapi2::variable_buffer ccs_end_1(1); + fapi2::buffer l_data_8; + fapi2::buffer l_data_16; + uint32_t l_port = i_addr.port; + + // CCS Array 0 Setup + + // Buffer conversions from inputs + FAPI_TRY(addr_16.insertFromRight(i_addr.row_addr, 0, 16)); + FAPI_TRY(addr_16.extract(l_data_16)); + l_data_16.reverse(); + FAPI_TRY(addr_16.insert((uint16_t)l_data_16)); + FAPI_TRY(bank_3.insertFromRight(i_addr.bank, 0, 3)); + FAPI_TRY(bank_3.extract(l_data_8, 0, 3)); + l_data_8.reverse(); + FAPI_TRY(bank_3.insertFromRight((uint8_t)l_data_8, 0 , 3)); + csn_8.flush<1>(); + + // Command structure setup + cke_4.flush<1>(); + FAPI_TRY(rasn_1.setBit(0)); + FAPI_TRY(casn_1.setBit(0)); + FAPI_TRY(wen_1.setBit(0)); + + FAPI_TRY(read_compare_1.clearBit(0)); + + // Final setup + odt_4.flush<0>(); + cal_type_4.flush<0>(); + FAPI_TRY(ddr4_activate_1.setBit(0)); + + FAPI_TRY(mss_ccs_inst_arry_0(i_target_mba, + io_instruction_number, + addr_16, + bank_3, + ddr4_activate_1, + rasn_1, + casn_1, + wen_1, + cke_4, + csn_8, + odt_4, + cal_type_4, + l_port)); + + // CCS Array 1 Setup + idles_16.flush<0>(); + FAPI_TRY(idles_16.insertFromRight(i_delay, 0, 16)); + repeat_16.flush<0>(); + FAPI_TRY(repeat_16.insertFromRight(i_repeat, 0, 16)); + pattern_20.flush<0>(); + read_compare_1.flush<0>(); + rank_cal_4.flush<0>(); + cal_enable_1.flush<0>(); + ccs_end_1.flush<0>(); + FAPI_TRY(mss_ccs_inst_arry_1(i_target_mba, + io_instruction_number, + idles_16, + repeat_16, + pattern_20, + read_compare_1, + rank_cal_4, + cal_enable_1, + ccs_end_1)); ++io_instruction_number; fapi_try_exit: @@ -2501,8 +3201,8 @@ fapi2::ReturnCode cs_decode(const fapi2::Target& i_targe if(i_stack_type == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS) { - FAPI_TRY(mrank.insert(i_addr.rank, 4, 4 , 0)); - FAPI_TRY(cid.insert(i_addr.rank, 4, 4, 4)); + FAPI_TRY(mrank.insert(i_addr.mrank, 4, 4, 4)); + FAPI_TRY(cid.insert(i_addr.srank, 4, 4, 4)); uint8_t mrank_u8 = 0; mrank.extract(mrank_u8, 0, 8); @@ -2513,6 +3213,7 @@ fapi2::ReturnCode cs_decode(const fapi2::Target& i_targe fapi2::CEN_MSS_CCS_MRANK_OUT_OF_BOUNDS() .set_INDEX_VALUE(mrank_u8), "mrank value: 0x%02X not supported\n", mrank_u8); + FAPI_ASSERT(cid_u8 < 8, fapi2::CEN_MSS_CCS_SRANK_OUT_OF_BOUNDS() .set_INDEX_VALUE(cid_u8), @@ -2531,14 +3232,14 @@ fapi2::ReturnCode cs_decode(const fapi2::Target& i_targe FAPI_TRY(o_csn_8.insert(cid_u8, 3, 1, 6)); } - FAPI_DBG("%s Row: 0x%04x, Col: 0x%04x, Mrank: %d, Srank: %d, Bank: %d, Port: %d\n", + FAPI_DBG("%s Row: %x, Col: %x, Mrank: %d, Srank: %d, Bank: %d, Port: %d\n", mss::c_str(i_target_mba), i_addr.row_addr, i_addr.col_addr, mrank_u8, cid_u8, i_addr.bank, i_addr.port); } else { - FAPI_TRY(o_csn_8.clearBit(i_addr.rank)); - FAPI_DBG("%s Row: 0x%04x, Col: 0x%04x, Rank: %d, Bank: %d, Port: %d\n", - mss::c_str(i_target_mba), i_addr.row_addr, i_addr.col_addr, i_addr.rank, i_addr.bank, i_addr.port); + FAPI_TRY(o_csn_8.clearBit(i_addr.mrank)); + FAPI_DBG("%s Row: %x, Col: %x, Rank: %d, Bank: %d, Port: %d\n", + mss::c_str(i_target_mba), i_addr.row_addr, i_addr.col_addr, i_addr.mrank, i_addr.bank, i_addr.port); } fapi_try_exit: diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_funcs.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_funcs.H index a1fa20c31..454cdb8fc 100755 --- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_funcs.H +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_funcs.H @@ -42,7 +42,8 @@ struct access_address { uint32_t row_addr; uint32_t col_addr; - uint8_t rank; + uint8_t mrank; + uint8_t srank; uint8_t bank; uint8_t port; }; @@ -360,6 +361,80 @@ fapi2::ReturnCode add_nop_to_ccs(const fapi2::Target& i_ const uint32_t i_delay, uint32_t& io_instruction_number); +/// @brief Add an MRS command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for MRS +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_mrs_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + uint32_t& io_instruction_number); + +/// @brief Add an ACT command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_activate_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + uint32_t& io_instruction_number); + +/// @brief Add a WR command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_write_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + uint32_t& io_instruction_number); + +/// @brief Add an ODT command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_repeat number of repeats to specify in this instruction +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_odt_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_repeat, + const uint32_t i_delay, + uint32_t& io_instruction_number); + +/// @brief Add a precharge all command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_delay delay associated with this instruction +/// @param[in] i_odt_wr value of ATTR_CEN_VPD_ODT_WR +/// @param[in] i_stack_type value of ATTR_CEN_EFF_STACK_TYPE +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_precharge_all_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_delay, + const uint8_t (&i_odt_wr)[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM], + const uint8_t (&i_stack_type)[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT], + uint32_t& io_instruction_number); + +/// @brief Add a DES command to the CCS program +/// @param[in] i_target_mba mba target +/// @param[in] i_addr address struct for command +/// @param[in] i_repeat number of repeats to specify in this instruction +/// @param[in] i_delay delay associated with this instruction +/// @param[in,out] io_instruction_number position in CCS program in which to insert command (will be incremented) +/// @return FAPI2_RC_SUCCESS iff successful +fapi2::ReturnCode add_des_with_repeat_to_ccs(const fapi2::Target& i_target_mba, + const access_address i_addr, + const uint32_t i_repeat, + const uint32_t i_delay, + uint32_t& io_instruction_number); + /// @brief Get the CSN representation of a given address /// @param[in] i_target_mba mba target /// @param[in] i_addr address struct for MRS diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.C index a53075350..ed4841acb 100644 --- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.C +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.C @@ -22,3 +22,218 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +#include +#include +#include +#include +#include +#include + +using namespace fapi2; + +extern "C" +{ + /// @brief Perform a PPR row repair operation + /// @param[in] i_target_mba mba target + /// @param[in] i_port port for repair + /// @param[in] i_mrank master rank of address to repair + /// @param[in] i_srank slave rank of address to repair + /// @param[in] i_bank bank bits of address to repair + /// @param[in] i_row row bits of address to repair + /// @param[in] i_dram_bitmap bitmap of DRAMs selected for repair (b'1 to repair, b'0 to not repair) + /// @return FAPI2_RC_SUCCESS iff successful + fapi2::ReturnCode p9c_mss_row_repair(const fapi2::Target& i_target_mba, + const uint8_t i_port, + const uint8_t i_mrank, + const uint8_t i_srank, + const uint8_t i_bank, + const uint32_t i_row, + const uint32_t i_dram_bitmap) + { + constexpr uint64_t REFRESH_BIT = CEN_MBA_MBAREF0Q_CFG_REFRESH_ENABLE; + constexpr uint32_t NUM_POLL = 10; + constexpr uint32_t WAIT_TIMER = 1500; + constexpr uint32_t ENABLE_PPR = 0x0020; + constexpr uint32_t DISABLE_PPR = 0; + constexpr uint8_t TMOD = 24; + + // This is the value to shift the input DRAM position to the last 20 bits of l_write_pattern + constexpr uint8_t DRAM_START_BIT = 44; + constexpr uint8_t DRAM_LEN = 64 - DRAM_START_BIT; + + const std::vector MR0_SHADOW_REGS = + { + CEN_MBA_DDRPHY_PC_MR0_PRI_RP0_P0, + CEN_MBA_DDRPHY_PC_MR0_PRI_RP1_P0, + CEN_MBA_DDRPHY_PC_MR0_PRI_RP2_P0, + CEN_MBA_DDRPHY_PC_MR0_PRI_RP3_P0, + CEN_MBA_DDRPHY_PC_MR0_PRI_RP0_P1, + CEN_MBA_DDRPHY_PC_MR0_PRI_RP1_P1, + CEN_MBA_DDRPHY_PC_MR0_PRI_RP2_P1, + CEN_MBA_DDRPHY_PC_MR0_PRI_RP3_P1, + }; + + // MRS address sequence for sPPR setup + // Note that we need to set a valid column address for these, so we use '0' + const std::vector l_mrs_addrs = + { + // Puts the DRAM into PPR mode + {ENABLE_PPR, 0, i_mrank, i_srank, MRS4_BA, i_port}, + // Writes the guard key sequence to MR0 (4 commands) + {0x0CFF, 0, i_mrank, i_srank, MRS0_BA, i_port}, + {0x07FF, 0, i_mrank, i_srank, MRS0_BA, i_port}, + {0x0BFF, 0, i_mrank, i_srank, MRS0_BA, i_port}, + {0x03FF, 0, i_mrank, i_srank, MRS0_BA, i_port}, + }; + + access_address l_addr = {i_row, 0, i_mrank, i_srank, i_bank, i_port}; + fapi2::buffer l_row; + fapi2::buffer l_bank; + fapi2::buffer l_saved_mr0; + fapi2::buffer l_reg_buffer; + fapi2::buffer l_dram_scratch; + uint64_t l_write_pattern = 0; + uint32_t l_instruction_number = 0; + uint8_t l_refresh = 0; + uint8_t l_dram_gen = 0; + uint8_t l_dram_width = 0; + uint8_t l_stack_type_u8array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; + uint8_t l_odt[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0}; + + uint8_t l_al = 0; + uint8_t l_trcd = 0; + uint8_t l_twr = 0; + uint8_t l_cwl = 0; + uint32_t l_trfc = 0; + uint8_t l_pl = 0; + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba, l_dram_gen)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_ODT_WR, i_target_mba, l_odt)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target_mba, l_stack_type_u8array)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_TRCD, i_target_mba, l_trcd)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WR, i_target_mba, l_twr)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_AL, i_target_mba, l_al)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_CWL, i_target_mba, l_cwl)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_TRFC, i_target_mba, l_trfc)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CA_PARITY_LATENCY, i_target_mba, l_pl)); + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target_mba, l_dram_width)); + + // DDR3 doesn't support sPPR, so bail unless we're DDR4 + FAPI_ASSERT(l_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4, + fapi2::CEN_MSS_ROW_REPAIR_NOT_SUPPORTED(). + set_TARGET_MBA(i_target_mba). + set_PORT(i_port). + set_MRANK(i_mrank). + set_DRAM_GEN(l_dram_gen), + "%s Row repair is not supported on DDR3 parts. Port%d mrank%d is %s", + mss::c_str(i_target_mba), i_port, i_mrank, (l_dram_gen == 1 ? "DDR3" : "Unknown DRAM gen")); + + // Compute the CCS write pattern to select the desired DRAM(s) + l_dram_scratch = i_dram_bitmap; + l_dram_scratch.invert(); + l_dram_scratch.extractToRight(l_write_pattern); + + // Save MR0 data before we write guard key sequence + FAPI_TRY(fapi2::getScom(i_target_mba, MR0_SHADOW_REGS[0], l_saved_mr0)); + + // Turn off refresh + FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_reg_buffer)); + l_refresh = l_reg_buffer.getBit(); + l_reg_buffer.clearBit(); + FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_reg_buffer)); + + // Precharge all ranks before we set sPPR mode + FAPI_TRY(add_precharge_all_to_ccs(i_target_mba, l_addr, l_trcd, l_odt, l_stack_type_u8array, l_instruction_number)); + + // Put the DRAM into sPPR mode + for (auto l_mrs_addr : l_mrs_addrs) + { + FAPI_TRY(add_mrs_to_ccs_ddr4(i_target_mba, l_mrs_addr, TMOD, l_instruction_number)); + } + + // Enable CCS and set RAS/CAS/WE high during idles + FAPI_DBG("%s Enabling CCS", mss::c_str(i_target_mba)); + FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_CCS_MODEQ, l_reg_buffer)); + FAPI_TRY(l_reg_buffer.setBit(29)); //Enable CCS + FAPI_TRY(l_reg_buffer.setBit(52)); //RAS high + FAPI_TRY(l_reg_buffer.setBit(53)); //CAS high + FAPI_TRY(l_reg_buffer.setBit(54)); //WE high + FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_CCS_MODEQ, l_reg_buffer)); + + // Subtract one from the instruction count because set_end_bit increments it + --l_instruction_number; + FAPI_TRY(mss_ccs_set_end_bit(i_target_mba, l_instruction_number), "CCS_SET_END_BIT FAILED"); + + // Execute the CCS program + FAPI_DBG("%s Executing the CCS array", mss::c_str(i_target_mba)); + FAPI_TRY(mss_execute_ccs_inst_array(i_target_mba, NUM_POLL, WAIT_TIMER), " EXECUTE_CCS_INST_ARRAY FAILED"); + l_instruction_number = 0; + + // Restore the MR0 shadow regs + for (const auto l_mr0_reg : MR0_SHADOW_REGS) + { + FAPI_TRY(fapi2::putScom(i_target_mba, l_mr0_reg, l_saved_mr0)); + } + + // Issue ACT command with bank and row fail address + FAPI_TRY(add_activate_to_ccs(i_target_mba, l_addr, l_trcd, l_instruction_number)); + + // Issue WR command with (tWR + WL + 10) cycles delay, values are the result of lab experimentation + FAPI_TRY(add_write_to_ccs(i_target_mba, l_addr, (l_twr + l_cwl + l_al + l_pl + 10), l_instruction_number)); + + // Write pattern (back up the instruction count so we hit the write instruction) + --l_instruction_number; + FAPI_TRY(mss_ccs_load_data_pattern(i_target_mba, l_instruction_number, l_write_pattern)); + ++l_instruction_number; + + // Issue precharge all command + FAPI_TRY(add_precharge_all_to_ccs(i_target_mba, l_addr, l_trcd, l_odt, l_stack_type_u8array, l_instruction_number)); + + // Issue DES command for tPGM_exit (12 clks) + FAPI_TRY(add_des_with_repeat_to_ccs(i_target_mba, l_addr, 0, 12, l_instruction_number)); + + // Take the DRAM out of PPR mode (MR4 command) + l_addr.row_addr = DISABLE_PPR; + l_addr.bank = MRS4_BA; + FAPI_TRY(add_mrs_to_ccs_ddr4(i_target_mba, l_addr, TMOD, l_instruction_number)); + + // Put the DRAM into the original MR0 mode + l_addr.bank = MRS0_BA; + FAPI_TRY(l_saved_mr0.clearBit(55)); //clear the dll reset. + l_saved_mr0.extractToRight(l_addr.row_addr, 46, 18); + FAPI_TRY(add_mrs_to_ccs_ddr4(i_target_mba, l_addr, TMOD, l_instruction_number)); + + // Enable CCS and set RAS/CAS/WE high during idles + FAPI_DBG("%s Enabling CCS", mss::c_str(i_target_mba)); + FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_CCS_MODEQ, l_reg_buffer)); + FAPI_TRY(l_reg_buffer.setBit(29)); //Enable CCS + FAPI_TRY(l_reg_buffer.setBit(52)); //RAS high + FAPI_TRY(l_reg_buffer.setBit(53)); //CAS high + FAPI_TRY(l_reg_buffer.setBit(54)); //WE high + FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_CCS_MODEQ, l_reg_buffer)); + + // Subtract one from the instruction count because set_end_bit increments it + --l_instruction_number; + FAPI_TRY(mss_ccs_set_end_bit(i_target_mba, l_instruction_number), "CCS_SET_END_BIT FAILED"); + + // Execute the CCS program + FAPI_DBG("%s Executing the CCS array", mss::c_str(i_target_mba)); + FAPI_TRY(mss_execute_ccs_inst_array(i_target_mba, NUM_POLL, WAIT_TIMER), " EXECUTE_CCS_INST_ARRAY FAILED"); + l_instruction_number = 0; + + // Disable CCS + FAPI_DBG("%s Disabling CCS", mss::c_str(i_target_mba)); + FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_CCS_MODEQ, l_reg_buffer)); + FAPI_TRY(l_reg_buffer.clearBit(29)); + FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_CCS_MODEQ, l_reg_buffer)); + + // Turn on refresh + FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_reg_buffer)); + l_reg_buffer.writeBit(l_refresh); + FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_reg_buffer)); + + fapi_try_exit: + return fapi2::current_err; + } + +} diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.H index 1d4af14b9..aa113d762 100644 --- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.H +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.H @@ -22,3 +22,39 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +#ifndef __P9C_MSS_ROW_REPAIR__ +#define __P9C_MSS_ROW_REPAIR__ + +#include + +typedef fapi2::ReturnCode (*p9c_mss_row_repair_FP_t)(const fapi2::Target& i_target_mba, + const uint8_t i_port, + const uint8_t i_mrank, + const uint8_t i_srank, + const uint8_t i_bank, + const uint32_t i_row, + const uint32_t i_dram_bitmap); + +extern "C" +{ + + /// @brief Perform a PPR row repair operation + /// @param[in] i_target_mba mba target + /// @param[in] i_port port for repair + /// @param[in] i_mrank master rank of address to repair + /// @param[in] i_srank slave rank of address to repair + /// @param[in] i_bank bank bits of address to repair + /// @param[in] i_row row bits of address to repair + /// @param[in] i_dram_bitmap bitmap of DRAMs selected for repair (b'1 to repair, b'0 to not repair) + /// @return FAPI2_RC_SUCCESS iff successful + fapi2::ReturnCode p9c_mss_row_repair(const fapi2::Target& i_target_mba, + const uint8_t i_port, + const uint8_t i_mrank, + const uint8_t i_srank, + const uint8_t i_bank, + const uint32_t i_row, + const uint32_t i_dram_bitmap); + +} + +#endif diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.mk index ea540b5ce..b291f595b 100644 --- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.mk +++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_row_repair.mk @@ -22,3 +22,10 @@ # permissions and limitations under the License. # # IBM_PROLOG_END_TAG +-include 00common.mk + +PROCEDURE=p9c_mss_row_repair +$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE))) +lib${PROCEDURE}_DEPLIBS+=p9c_mss_ddr4_funcs +lib${PROCEDURE}_DEPLIBS+=p9c_mss_funcs +$(call BUILD_PROCEDURE) diff --git a/src/import/chips/centaur/procedures/xml/error_info/p9c_mss_funcs_errors.xml b/src/import/chips/centaur/procedures/xml/error_info/p9c_mss_funcs_errors.xml index 61a54bfb5..df5d195ec 100644 --- a/src/import/chips/centaur/procedures/xml/error_info/p9c_mss_funcs_errors.xml +++ b/src/import/chips/centaur/procedures/xml/error_info/p9c_mss_funcs_errors.xml @@ -206,4 +206,17 @@ + + RC_CEN_MSS_ROW_REPAIR_NOT_SUPPORTED + An sPPR row repair operation was attempted on a DDR3 part, which doesn't support it. + TARGET_MBA + PORT + MRANK + DRAM_GEN + + CODE + HIGH + + + -- cgit v1.2.1