From cfb19f068394a358ce21fa3976d0aca834bb3030 Mon Sep 17 00:00:00 2001 From: Thi Tran Date: Thu, 20 Feb 2014 08:55:11 -0600 Subject: INITPROC: Hostboot SW245013 Centaur DMI & training update Change-Id: I09a9d02c7070a09378220030f16c5ce2b040c38c CQ:SW245013 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/9040 Tested-by: Jenkins Server Reviewed-by: Thi N. Tran Reviewed-by: A. Patrick Williams III --- .../mss_draminit_mc/mss_draminit_mc.C | 99 ++- .../memory_mss_generic_shmoo.xml | 21 +- .../mss_draminit_trainadv/mss_generic_shmoo.C | 222 +++++- .../mss_draminit_training/mss_draminit_training.C | 773 ++++++++++++--------- 4 files changed, 742 insertions(+), 373 deletions(-) (limited to 'src/usr/hwpf/hwp/dram_training') diff --git a/src/usr/hwpf/hwp/dram_training/mss_draminit_mc/mss_draminit_mc.C b/src/usr/hwpf/hwp/dram_training/mss_draminit_mc/mss_draminit_mc.C index 356b3dc70..7159a0736 100644 --- a/src/usr/hwpf/hwp/dram_training/mss_draminit_mc/mss_draminit_mc.C +++ b/src/usr/hwpf/hwp/dram_training/mss_draminit_mc/mss_draminit_mc.C @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012,2013 */ +/* COPYRIGHT International Business Machines Corp. 2012,2014 */ /* */ /* p1 */ /* */ @@ -20,7 +20,7 @@ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: mss_draminit_mc.C,v 1.43 2013/10/28 15:10:24 dcadiga Exp $ +// $Id: mss_draminit_mc.C,v 1.45 2014/02/17 15:16:14 lapietra Exp $ //------------------------------------------------------------------------------ // *! (C) Copyright International Business Machines Corp. 2011 // *! All Rights Reserved -- Property of IBM @@ -44,6 +44,8 @@ //------------------------------------------------------------------------------ // Version:| Author: | Date: | Comment: //---------|----------|---------|----------------------------------------------- +// 1.45 | dcadiga |14-FEB-14| Periodic Cal Fix for DD2 +// 1.44 | bellows |12-FEB-14| Workaround for ENABLE_RCE_WITH_OTHER_ERRORS_HW246685 // 1.43 | dcadiga |28-OCT-13| Fixed code review comments for parent chip and typos // 1.42 | dcadiga |16-OCT-13| Fixed Code Review Comments, added DD2.X EC check for parity on 32GB // 1.41 | dcadiga |16-OCT-13| repeating Brent's test @@ -353,36 +355,76 @@ ReturnCode mss_enable_periodic_cal (Target& i_target) if (memcal_iterval != 0) { - //Phase Select Fix for DD1.1 + + + + uint8_t attr_centaur_ec_rdclk_pr_update_hw236658_fixed; + rc = FAPI_ATTR_GET(ATTR_CENTAUR_EC_RDCLK_PR_UPDATE_HW236658_FIXED, &i_target, attr_centaur_ec_rdclk_pr_update_hw236658_fixed); + if(rc) return rc; + + if(!attr_centaur_ec_rdclk_pr_update_hw236658_fixed){ + + //Check EC, Disable Phase Select Update for DD2 HW + //Phase Select Fix for DD1.1 + rc_num = rc_num | data_buffer_64.flushTo0(); + rc_num = rc_num | data_buffer_64.setBit(52); + if(rc_num) + { + rc.setEcmdError(rc_num); + return rc; + } + + + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_0_0x800000120301143F,data_buffer_64); + if(rc) return rc; + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_1_0x800004120301143F,data_buffer_64); + if(rc) return rc; + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_2_0x800008120301143F,data_buffer_64); + if(rc) return rc; + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_3_0x80000C120301143F,data_buffer_64); + if(rc) return rc; + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_4_0x800010120301143F,data_buffer_64); + if(rc) return rc; + + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_0_0x800100120301143F,data_buffer_64); + if(rc) return rc; + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_1_0x800104120301143F,data_buffer_64); + if(rc) return rc; + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_2_0x800108120301143F,data_buffer_64); + if(rc) return rc; + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_3_0x80010C120301143F,data_buffer_64); + if(rc) return rc; + rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_4_0x800110120301143F,data_buffer_64); + + + } + + //Disable Periodic Read Centering for ALL HW rc_num = rc_num | data_buffer_64.flushTo0(); - rc_num = rc_num | data_buffer_64.setBit(52); - if(rc_num) + if(rc_num) { rc.setEcmdError(rc_num); return rc; } - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_0_0x800000120301143F,data_buffer_64); - if(rc) return rc; - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_1_0x800004120301143F,data_buffer_64); - if(rc) return rc; - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_2_0x800008120301143F,data_buffer_64); - if(rc) return rc; - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_3_0x80000C120301143F,data_buffer_64); - if(rc) return rc; - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P0_4_0x800010120301143F,data_buffer_64); - if(rc) return rc; + rc = fapiGetScom(i_target,DPHY01_DDRPHY_PC_PER_CAL_CONFIG_P0_0x8000C00B0301143F,data_buffer_64); + rc_num = rc_num | data_buffer_64.clearBit(54); + rc = fapiPutScom(i_target,DPHY01_DDRPHY_PC_PER_CAL_CONFIG_P0_0x8000C00B0301143F,data_buffer_64); + + + + rc_num = rc_num | data_buffer_64.flushTo0(); + if(rc_num) + { + rc.setEcmdError(rc_num); + return rc; + } + rc = fapiGetScom(i_target,DPHY01_DDRPHY_PC_PER_CAL_CONFIG_P1_0x8001C00B0301143F,data_buffer_64); + rc_num = rc_num | data_buffer_64.clearBit(54); + rc = fapiPutScom(i_target,DPHY01_DDRPHY_PC_PER_CAL_CONFIG_P1_0x8001C00B0301143F,data_buffer_64); - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_0_0x800100120301143F,data_buffer_64); - if(rc) return rc; - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_1_0x800104120301143F,data_buffer_64); - if(rc) return rc; - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_2_0x800108120301143F,data_buffer_64); - if(rc) return rc; - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_3_0x80010C120301143F,data_buffer_64); - if(rc) return rc; - rc = fapiPutScom(i_target,DPHY01_DDRPHY_DP18_RD_DIA_CONFIG5_P1_4_0x800110120301143F,data_buffer_64); if(rc) return rc; + //Mem Cal Enabled rc_num = rc_num | data_buffer_64.flushTo0(); if(rc_num) @@ -484,6 +526,15 @@ ReturnCode mss_enable_control_bit_ecc (Target& i_target) rc_num = rc_num | ecc1_data_buffer_64.clearBit(1); rc_num = rc_num | ecc1_data_buffer_64.setBit(3); + uint8_t attr_centaur_ec_enable_rce_with_other_errors_hw246685; + rc = FAPI_ATTR_GET(ATTR_CENTAUR_EC_ENABLE_RCE_WITH_OTHER_ERRORS_HW246685, &i_target, attr_centaur_ec_enable_rce_with_other_errors_hw246685); + if(rc) return rc; + + if(attr_centaur_ec_enable_rce_with_other_errors_hw246685) { + rc_num = rc_num | ecc0_data_buffer_64.setBit(16); + rc_num = rc_num | ecc1_data_buffer_64.setBit(16); + } + if (rc_num) { FAPI_ERR( "mss_enable_control_bit_ecc: Error setting up buffers"); diff --git a/src/usr/hwpf/hwp/dram_training/mss_draminit_trainadv/memory_mss_generic_shmoo.xml b/src/usr/hwpf/hwp/dram_training/mss_draminit_trainadv/memory_mss_generic_shmoo.xml index ef57ff96a..6e6af1b6e 100644 --- a/src/usr/hwpf/hwp/dram_training/mss_draminit_trainadv/memory_mss_generic_shmoo.xml +++ b/src/usr/hwpf/hwp/dram_training/mss_draminit_trainadv/memory_mss_generic_shmoo.xml @@ -21,7 +21,7 @@ - + @@ -31,11 +31,22 @@ The mss_generic_shmoo file found an MCBIST Failure - MCB_STATUS - MBA_CHIPLET + + MBA_CHIPLET + TARGET_TYPE_DIMM + MBA_PORT_NUMBER + MBA_DIMM_NUMBER + HIGH + + + MBA_CHIPLET + TARGET_TYPE_DIMM + MBA_PORT_NUMBER + MBA_DIMM_NUMBER + + - - + \ No newline at end of file diff --git a/src/usr/hwpf/hwp/dram_training/mss_draminit_trainadv/mss_generic_shmoo.C b/src/usr/hwpf/hwp/dram_training/mss_draminit_trainadv/mss_generic_shmoo.C index a634456ab..88a56df88 100644 --- a/src/usr/hwpf/hwp/dram_training/mss_draminit_trainadv/mss_generic_shmoo.C +++ b/src/usr/hwpf/hwp/dram_training/mss_draminit_trainadv/mss_generic_shmoo.C @@ -21,7 +21,7 @@ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: mss_generic_shmoo.C,v 1.86 2014/01/24 17:18:50 sasethur Exp $ +// $Id: mss_generic_shmoo.C,v 1.87 2014/02/07 16:54:14 sasethur Exp $ // *!*************************************************************************** // *! (C) Copyright International Business Machines Corp. 1997, 1998 // *! All Rights Reserved -- Property of IBM @@ -40,6 +40,7 @@ //------------------------------------------------------------------------------ // Version:|Author: | Date: | Comment: // --------|--------|---------|-------------------------------------------------- +// 1.87 |abhijsau|7-Feb-14| added sanity check and error call out for schmoo's , removed printing of disconnected DQS. // 1.86 |abhijsau|24-Jan-14| Fixed code as per changes in access delay error check // 1.85 |mjjones |24-Jan-14| Fixed layout and error handling for RAS Review // 1.84 |abhijit |16-JAN-14| Changed EFF_DIMM_TYPE attribute to ATTR_EFF_CUSTOM_DIMM @@ -336,6 +337,11 @@ fapi::ReturnCode generic_shmoo::run(const fapi::Target & i_target, if (rc) return rc; rc = schmoo_setup_mcb(i_target); if (rc) return rc; + + //sanity check + //rc = sanity_check(i_target); + //if (rc) return rc; + //Find RIGHT BOUND OR SETUP BOUND rc = find_bound(i_target, RIGHT); if (rc) return rc; @@ -379,6 +385,10 @@ fapi::ReturnCode generic_shmoo::run(const fapi::Target & i_target, { rc = schmoo_setup_mcb(i_target); if (rc) return rc; + + rc = sanity_check(i_target); + if (rc) return rc; + } rc = set_all_binary(i_target, RIGHT); if (rc) return rc; @@ -482,6 +492,19 @@ fapi::ReturnCode generic_shmoo::sanity_check(const fapi::Target & i_target) uint8_t l_mcb_status = 0; uint8_t l_CDarray0[80] = { 0 }; uint8_t l_CDarray1[80] = { 0 }; + + uint8_t l_byte, l_rnk; + uint8_t l_nibble; + uint8_t l_n = 0; + uint8_t l_p = 0; + uint8_t i_rp = 0; + uint8_t rank = 0; + uint8_t l_faulted_rank = 255; + uint8_t l_faulted_port = 255; + uint8_t l_faulted_dimm = 255; + uint8_t l_memory_health = 0; + uint8_t l_max_byte = 10; + //uint8_t l_max_nibble = 20; struct Subtest_info l_sub_info[30]; @@ -501,12 +524,50 @@ fapi::ReturnCode generic_shmoo::sanity_check(const fapi::Target & i_target) rc = mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq); if (rc) return rc; + + for (l_p = 0; l_p < MAX_PORT; l_p++) + { + for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; ++l_rnk) + {// Byte loop + rc = mss_getrankpair(i_target, l_p, 0, &i_rp, valid_rank); + if (rc) return rc; + rank = valid_rank[l_rnk]; - if (l_mcb_status) + l_n = 0; + for (l_byte = 0; l_byte < l_max_byte; ++l_byte) + { + //Nibble loop + for (l_nibble = 0; l_nibble < MAX_NIBBLES; ++l_nibble) + { + if (mcbist_error_map[l_p][l_rnk][l_byte][l_nibble] == 1) + { + l_memory_health = 1; + l_faulted_rank = rank; + l_faulted_port = l_p; + if(rank>3){ + l_faulted_dimm = 1; + }else{ + l_faulted_dimm = 0; + } + break; + } + + l_n++; + + } + } + } + } + + + //////////////// changed the check condition ... The error call out need to gard the dimm=l_faulted_dimm(0 or 1) //// port=l_faulted_port(0 or 1) target=i_target ... + if (l_memory_health) { - FAPI_ERR("generic_shmoo:sanity_check failed !! MCBIST failed on intial run , memory is not in good state aborting shmoo"); - const uint8_t & MCB_STATUS = l_mcb_status; + FAPI_INF("generic_shmoo:sanity_check failed !! MCBIST failed on intial run , memory is not in good state needs investigation port=%d rank=%d dimm=%d", + l_faulted_port, l_faulted_rank, l_faulted_dimm); const fapi::Target & MBA_CHIPLET = i_target; + const uint8_t & MBA_PORT_NUMBER = l_faulted_port; + const uint8_t & MBA_DIMM_NUMBER = l_faulted_dimm; FAPI_SET_HWP_ERROR(rc, RC_MSS_GENERIC_SHMOO_MCBIST_FAILED); return rc; } @@ -615,8 +676,7 @@ fapi::ReturnCode generic_shmoo::check_error_map(const fapi::Target & i_target, uint8_t l_byte_is; uint8_t l_nibble_is; uint8_t l_n = 0; - uint8_t l_i = 0; - uint8_t l_dq = 0; + pass = 1; uint8_t l_p = 0; input_type l_input_type_e = ISDIMM_DQ; @@ -626,6 +686,8 @@ fapi::ReturnCode generic_shmoo::check_error_map(const fapi::Target & i_target, uint8_t rank = 0; uint8_t l_max_byte = 10; uint8_t l_max_nibble = 20; + uint8_t l_i = 0; + uint8_t l_dq = 0; uint8_t l_CDarray0[80] = { 0 }; uint8_t l_CDarray1[80] = { 0 }; @@ -3428,7 +3490,7 @@ fapi::ReturnCode generic_shmoo::print_report(const fapi::Target & i_target) fapi::ReturnCode rc; uint8_t l_rnk, l_byte, l_nibble, l_bit; - uint8_t l_dq = 0; + //uint8_t l_dq = 0; uint8_t l_rp = 0; uint8_t l_p = 0; uint8_t i_rank = 0; @@ -3439,9 +3501,23 @@ fapi::ReturnCode generic_shmoo::print_report(const fapi::Target & i_target) uint8_t l_attr_eff_num_drops_per_port_u8 = 0; uint8_t l_attr_eff_dram_width_u8 = 0; uint16_t l_total_margin = 0; + uint8_t l_i = 0; + uint8_t l_dq = 0; + uint8_t l_flag = 0; + uint8_t l_CDarray0[80] = { 0 }; + uint8_t l_CDarray1[80] = { 0 }; + char * l_pMike = new char[128]; char * l_str = new char[128]; + + rc = mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, + count_bad_dq); + if (rc) + { + FAPI_ERR("generic_shmoo::print report: mcb_error_map failed!!"); + return rc; + } fapi::Target l_target_centaur; @@ -3484,7 +3560,7 @@ fapi::ReturnCode generic_shmoo::print_report(const fapi::Target & i_target) //FAPI_INF("%s:num_drops_per_port = %d on %s.", l_attr_eff_num_drops_per_port_u8, i_target.toEcmdString()); //FAPI_INF("%s:num_ranks = %d on %s.", iv_MAX_RANKS,i_target.toEcmdString()); - //FAPI_INF("%s:dram_width = %d on %s. \n\n", l_attr_eff_dram_width_u8, i_target.toEcmdString()); + FAPI_INF("dram_width = %d \n\n", l_attr_eff_dram_width_u8); FAPI_INF("%s:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", i_target.toEcmdString()); //// Based on schmoo param the print will change eventually @@ -3514,7 +3590,37 @@ fapi::ReturnCode generic_shmoo::print_report(const fapi::Target & i_target) { //Nibble loop for (l_nibble = 0; l_nibble < MAX_NIBBLES; ++l_nibble) - { + { + + l_dq=8 * l_byte + 4 * l_nibble; + l_flag=0; + if (l_p == 0) + { + for (l_i = 0; l_i < count_bad_dq[0]; l_i++) + { + if (l_CDarray0[l_i] == l_dq) + { + l_flag=1; + + } + } + } + else + { + for (l_i = 0; l_i < count_bad_dq[1]; l_i++) + { + if (l_CDarray1[l_i] == l_dq) + { + l_flag=1; + + } + } + } + + if(l_flag==1) + { + continue; + } for (l_bit = 0; l_bit < MAX_BITS; ++l_bit) { l_dq = 8 * l_byte + 4 * l_nibble + l_bit; @@ -3569,6 +3675,20 @@ fapi::ReturnCode generic_shmoo::print_report_dqs(const fapi::Target & i_target) uint8_t l_by8_dqs = 0; char * l_pMike = new char[128]; char * l_str = new char[128]; + + uint8_t l_i = 0; + uint8_t l_dq = 0; + uint8_t l_flag = 0; + uint8_t l_CDarray0[80] = { 0 }; + uint8_t l_CDarray1[80] = { 0 }; + + rc = mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, + count_bad_dq); + if (rc) + { + FAPI_ERR("generic_shmoo::print report: mcb_error_map failed!!"); + return rc; + } if (iv_dmm_type == 1) { @@ -3658,7 +3778,36 @@ fapi::ReturnCode generic_shmoo::print_report_dqs(const fapi::Target & i_target) l_nibble = l_nibble * 2; } } - + l_dq=4* l_nibble; + l_flag=0; + if (l_p == 0) + { + for (l_i = 0; l_i < count_bad_dq[0]; l_i++) + { + if (l_CDarray0[l_i] == l_dq) + { + l_flag=1; + + } + } + } + else + { + for (l_i = 0; l_i < count_bad_dq[1]; l_i++) + { + if (l_CDarray1[l_i] == l_dq) + { + l_flag=1; + + } + } + } + + if(l_flag==1) + { + continue; + } + l_total_margin = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[l_rnk].K.left_margin_val[l_nibble] + SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[l_rnk].K.right_margin_val[l_nibble]; @@ -3942,11 +4091,7 @@ fapi::ReturnCode generic_shmoo::get_margin_dqs_by8(const fapi::Target & i_target SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[l_rnk].K.left_margin_val[l_nibble] = ((SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[l_rnk].K.curr_val[l_nibble] - SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[l_rnk].K.lb_regval[l_nibble]) - * l_factor) / l_factor_ps;//((1/uint32_t_freq*1000000)/128); - //SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[l_rnk].K.total_margin[l_nibble]=SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[l_rnk].K.right_margin_val[l_nibble]+SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[l_rnk].K.left_margin_val[l_nibble]; - // SHMOO[iv_shmoo_type].MBA.P[l_p].S[l_rnk].K.total_margin[l_nibble]=SHMOO[iv_shmoo_type].MBA.P[l_p].S[l_rnk].K.right_margin_val[l_nibble]+SHMOO[iv_shmoo_type].MBA.P[l_p].S[l_rnk].K.left_margin_val[l_nibble]; - //FAPI_INF("\n Abhijit is here after %d and port=%d \n",l_nibble,l_p); - //FAPI_INF("\n Abhijit is here after 2 %d \n",l_rnk); + * l_factor) / l_factor_ps; } } } @@ -3968,9 +4113,22 @@ fapi::ReturnCode generic_shmoo::get_min_margin(const fapi::Target & i_target, uint8_t l_rnk, l_byte, l_nibble, l_bit, i_rank; uint16_t l_temp_right = 4800; uint16_t l_temp_left = 4800; - uint8_t l_dq = 0; + //uint8_t l_dq = 0; uint8_t l_rp = 0; uint8_t l_p = 0; + uint8_t l_i = 0; + uint8_t l_dq = 0; + uint8_t l_flag = 0; + uint8_t l_CDarray0[80] = { 0 }; + uint8_t l_CDarray1[80] = { 0 }; + + rc = mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, + count_bad_dq); + if (rc) + { + FAPI_ERR("generic_shmoo::print report: mcb_error_map failed!!"); + return rc; + } for (l_p = 0; l_p < MAX_PORT; l_p++) { @@ -3985,7 +4143,37 @@ fapi::ReturnCode generic_shmoo::get_min_margin(const fapi::Target & i_target, { //Nibble loop for (l_nibble = 0; l_nibble < MAX_NIBBLES; ++l_nibble) - { + { + l_dq=8 * l_byte + 4 * l_nibble; + l_flag=0; + if (l_p == 0) + { + for (l_i = 0; l_i < count_bad_dq[0]; l_i++) + { + if (l_CDarray0[l_i] == l_dq) + { + l_flag=1; + + } + } + } + else + { + for (l_i = 0; l_i < count_bad_dq[1]; l_i++) + { + if (l_CDarray1[l_i] == l_dq) + { + l_flag=1; + + } + } + } + + if(l_flag==1) + { + continue; + } + for (l_bit = 0; l_bit < MAX_BITS; ++l_bit) { l_dq = 8 * l_byte + 4 * l_nibble + l_bit; diff --git a/src/usr/hwpf/hwp/dram_training/mss_draminit_training/mss_draminit_training.C b/src/usr/hwpf/hwp/dram_training/mss_draminit_training/mss_draminit_training.C index f5b739867..b83472316 100644 --- a/src/usr/hwpf/hwp/dram_training/mss_draminit_training/mss_draminit_training.C +++ b/src/usr/hwpf/hwp/dram_training/mss_draminit_training/mss_draminit_training.C @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2012,2013 */ +/* COPYRIGHT International Business Machines Corp. 2012,2014 */ /* */ /* p1 */ /* */ @@ -20,7 +20,7 @@ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: mss_draminit_training.C,v 1.70 2013/11/11 20:51:15 jdsloat Exp $ +// $Id: mss_draminit_training.C,v 1.72 2014/02/15 00:25:56 mwuu Exp $ //------------------------------------------------------------------------------ // Don't forget to create CVS comments when you check in your changes! //------------------------------------------------------------------------------ @@ -28,11 +28,16 @@ //------------------------------------------------------------------------------ // Version:| Author: | Date: | Comment: //---------|----------|---------|------------------------------------------------ +// 1.72 | mwuu |14-FEB-14| Fixed x4 spare case when mss_c4_phy returns bad +// | | | data with workaround +// 1.71 | mwuu |13-FEB-14| Updated get/setC4dq2reg, mss_set/get_bbm_regs FNs +// | | | to use access_delay_regs for dq/dqs pin mapping. +// | | | Added mss_get_dqs_lane helper FN. // 1.70 | jdsloat | 11/11/13| Changed EFF attributes to VPD named attributes // 1.69 | jdsloat |06-OCT-13| Removed Control Switch Attribute // 1.68 | bellows |16-SEP-13| Hostboot compile update // 1.67 | kcook |13-SEP-13| Updated define FAPI_LRDIMM token. -// 1.66 | kcook |27-AUG-13| Moved main LRDIMM sections into separate file. +// 1.66 | kcook |27-AUG-13| Moved main LRDIMM sections into separate file. // | | | Removed reference to ATTR_LAB_USE_JTAG_MODE. // | mwuu | | Added ATTR_MSS_DISABLE1_REG_FIXED for bbm FN for DD2. // 1.65 | kcook |16-AUG-13| Added LRDIMM support. Use with mss_funcs.C v1.32. @@ -131,6 +136,7 @@ // 1.2 | jdsloat |14-Jul-11| Proper call name fix // 1.1 | jdsloat |22-Apr-11| Initial draft + //---------------------------------------------------------------------- // FAPI function Includes //---------------------------------------------------------------------- @@ -145,8 +151,7 @@ #include #include #include - - +#include "mss_access_delay_reg.H" #ifndef FAPI_LRDIMM @@ -172,6 +177,7 @@ const uint8_t MRS1_BA = 1; const uint8_t MRS2_BA = 2; #define MAX_PORTS 2 +#define MAX_DIMMS 2 #define MAX_PRI_RANKS 4 #define TOTAL_BYTES 10 #define BITS_PER_REG 16 @@ -204,10 +210,11 @@ ReturnCode mss_read_center_workaround(Target& i_target, uint8_t i_mbaPosition, u ReturnCode mss_read_center_second_workaround(Target& i_target); ReturnCode mss_reset_delay_values(Target& i_target); -ReturnCode getC4dq2reg(const Target &i_mba, const uint8_t i_port, const uint8_t i_dimm, const uint8_t i_rank, ecmdDataBufferBase &o_reg); -ReturnCode setC4dq2reg(const Target &i_mba, const uint8_t i_port, const uint8_t i_dimm, const uint8_t i_rank, ecmdDataBufferBase &o_reg); +ReturnCode getC4dq2reg(const Target &i_mba, const uint8_t i_port, const uint8_t i_dimm, const uint8_t i_rank, ecmdDataBufferBase &o_reg, uint8_t &is_clean); +ReturnCode setC4dq2reg(const Target &i_mba, const uint8_t i_port, const uint8_t i_dimm, const uint8_t i_rank, const ecmdDataBufferBase &i_reg); ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target); ReturnCode mss_get_bbm_regs (const fapi::Target & mba_target); +ReturnCode mss_get_dqs_lane (const fapi::Target & i_mba, const uint8_t i_port, const uint8_t i_block, const uint8_t i_quad, uint8_t &lane); ReturnCode mss_draminit_training(Target& i_target) @@ -328,7 +335,7 @@ ReturnCode mss_draminit_training_cloned(Target& i_target) if(rc) return rc; uint8_t dimm_type; - rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_TYPE, &i_target, dimm_type); + rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_TYPE, &i_target, dimm_type); if(rc) return rc; @@ -3085,7 +3092,7 @@ ReturnCode mss_rtt_nom_rtt_wr_swap( fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) { // Flash to registers. - // disable0=dq bits, disable1=dqs (need to use swizzle), + // disable0=dq bits, disable1=dqs(+,-) // wrclk_en=dqs follows quad, same as disable0 const uint64_t disable_reg[MAX_PORTS][MAX_PRI_RANKS][DP18_INSTANCES] = { @@ -3149,65 +3156,30 @@ fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) ENUM_ATTR_EFF_PRIMARY_RANK_GROUP3_INVALID, }; - const uint8_t disable1_mask_lookup[4][DP18_INSTANCES][4] = { // for swizzle map - // port 0 - // q0 q1 q2 q3 - { {0xC0,0x30,0x03,0x0C}, // DP18 block 0 instance - {0xC0,0x30,0x03,0x0C}, // ... block 1 - {0xC0,0x30,0x0C,0x03}, // ... block 2 - {0xC0,0x30,0x0C,0x03}, // ... block 3 - {0xC0,0x30,0x0C,0x03} // ... block 4 - }, - // port 1 - { {0x30,0xC0,0x0C,0x03}, // 0xC0 = disable lanes 16,17 - {0x30,0xC0,0x0C,0x03}, // 0x30 = disable lanes 18,19 - {0xC0,0x30,0x0C,0x03}, // 0x0C = disable lanes 20,21 - {0xC0,0x30,0x0C,0x03}, // 0x03 = disable lanes 22,23 - {0xC0,0x30,0x03,0x0C} - }, - // port 2 - { {0xC0,0x30,0x0C,0x03}, - {0xC0,0x30,0x03,0x0C}, - {0xC0,0x30,0x0C,0x03}, - {0xC0,0x30,0x0C,0x03}, - {0xC0,0x30,0x0C,0x03} - }, - // port 3 - { {0xC0,0x30,0x0C,0x03}, - {0xC0,0x30,0x0C,0x03}, - {0xC0,0x30,0x03,0x0C}, - {0x30,0xC0,0x0C,0x03}, - {0xC0,0x30,0x0C,0x03} - } - }; - const uint16_t wrclk_disable_mask[] = { // by quads 0x8800, 0x4400, 0x2280, 0x1140 }; - uint8_t l_dram_width, l_mbaPos, l_disable1_fixed; + uint8_t l_dram_width, l_disable1_fixed; uint64_t l_addr; - // 0x8000007d0301143f - const uint64_t l_disable1_addr_offset = 0x0000000100000000ull; // from disable0 register - // 0x800000050301143f - const uint64_t l_wrclk_en_addr_mask = 0xFFFFFF07FFFFFFFFull; // from disable1 register + // 0x8000007d0301143f from disable0 register + const uint64_t l_disable1_addr_offset = 0x0000000100000000ull; + // 0x800000050301143f from disable1 register + const uint64_t l_wrclk_en_addr_mask = 0xFFFFFF07FFFFFFFFull; ReturnCode rc; ecmdDataBufferBase data_buffer(64); ecmdDataBufferBase db_reg(BITS_PER_PORT); uint32_t l_ecmdRc = ECMD_DBUF_SUCCESS; - uint8_t prg[MAX_PRI_RANKS][MAX_PORTS]; // primary rank group values + uint8_t prg[MAX_PRI_RANKS][MAX_PORTS]; // primary rank group values - FAPI_INF("Running set bad bits FN:mss_set_bbm_regs," - " input Target: %s", mba_target.toEcmdString()); + FAPI_INF("Running flash->registers(set)"); std::vector mba_dimms; fapiGetAssociatedDimms(mba_target, mba_dimms); // functional dimms - FAPI_INF("***-------- Found %i functional DIMMS --------***", - mba_dimms.size()); - - // ATTR_EFF_PRIMARY_RANK_GROUP0[port], GROUP1[port], GROUP2[port], GROUP3[port] + // ATTR_EFF_PRIMARY_RANK_GROUP0[port], GROUP1[port], + // GROUP2[port], GROUP3[port] rc=FAPI_ATTR_GET(ATTR_EFF_PRIMARY_RANK_GROUP0, &mba_target, prg[0]); if(rc) return rc; rc=FAPI_ATTR_GET(ATTR_EFF_PRIMARY_RANK_GROUP1, &mba_target, prg[1]); @@ -3217,9 +3189,6 @@ fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) rc=FAPI_ATTR_GET(ATTR_EFF_PRIMARY_RANK_GROUP3, &mba_target, prg[3]); if(rc) return rc; - rc=FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &mba_target, l_mbaPos); - if(rc) return rc; - rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &mba_target, l_dram_width); if(rc) return rc; @@ -3228,7 +3197,7 @@ fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) if(rc) return rc; rc = FAPI_ATTR_GET(ATTR_MSS_DISABLE1_REG_FIXED, &l_target_centaur, l_disable1_fixed); - if(rc) return rc; + if(rc) return rc; switch (l_dram_width) { @@ -3261,23 +3230,22 @@ fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) } for (uint8_t port = 0; port < MAX_PORTS; port++ ) // [0:1] { - uint8_t aport = (l_mbaPos*2) + port; - // loop through primary ranks [0:3] for (uint8_t prank = 0; prank < MAX_PRI_RANKS; prank++ ) { uint8_t dimm = prg[prank][port] >> 2; uint8_t rank = prg[prank][port] & 0x03; uint16_t l_data = 0; + uint8_t is_clean = 1; if (prg[prank][port] == rg_invalid[prank]) // invalid rank { - FAPI_INF("Primary rank group %i is INVALID, continuing...", + FAPI_DBG("Primary rank group %i: INVALID, continuing...", prank); continue; } - rc = getC4dq2reg(mba_target, port, dimm, rank, db_reg); + rc = getC4dq2reg(mba_target, port, dimm, rank, db_reg, is_clean); if (rc) { FAPI_ERR("Error from getting register bitmap port=%i: " @@ -3286,23 +3254,23 @@ fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) return rc; } // quick test to move on to next rank if no bits need to be set - if (db_reg.getNumBitsSet(0, BITS_PER_PORT) == 0) + if (is_clean == 1) // Note ignores spares that match attribute { - FAPI_INF("No bad bits found for p%i:d%i:r%i(rg%i):cs%i", - port, dimm, rank, prank, prg[prank][port]); + FAPI_INF("Primary rank group %i: No bad bits found for " + "p%i:d%i:r%i:cs%i", prank, port, dimm, rank, + prg[prank][port]); continue; } - for ( uint8_t i=0; i < DP18_INSTANCES; i++ ) // dp18 [0:4] { - uint16_t disable1_data = 0; + uint8_t disable1_data = 0; uint16_t wrclk_mask = 0; // check or not to check(always set register)? l_data = db_reg.getHalfWord(i); if (l_data == 0) { - FAPI_INF("DP18_%i has no bad bits set, continuing...", i); + FAPI_DBG("\tDP18_%i has no bad bits set, continuing...", i); continue; } // clear bits 48:63 @@ -3315,18 +3283,47 @@ fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) rc.setEcmdError(l_ecmdRc); return rc; } - - if (l_dram_width == 4) { // disable entire nibble if bad bit found - uint16_t mask = 0xF000; - for (uint8_t n=0; n < 4; n++) { // check each nibble - uint16_t nmask = mask >> (4*n); - if ((nmask & l_data) > 0) { - l_data = l_data | nmask; - FAPI_INF("Disabling nibble %i",n); + + for (uint8_t n=0; n < 4; n++) // check each nibble + { + uint16_t nmask = 0xF000 >> (4*n); + if (l_dram_width == 4) + { + if ((nmask & l_data) > 0) // bad bit(s) in nibble + { + // For Marc Gollub, since repair for x4 DRAM is in nibble + // granularity. Also due to higher chance of hitting dq0 of + // Micron causing write leveling to fail for entire x4 DRAM. + // Will also save a re-training loop. Complement in get_bbm_regs. + + l_data = l_data | nmask; // set entire nibble + FAPI_INF("Disabling entire nibble %i",n); + rc = mss_get_dqs_lane(mba_target, port, i, n, + disable1_data); + if (rc) return rc; + wrclk_mask |= wrclk_disable_mask[n]; + } + } // end x4 + else // width == 8+? + { + if ((n % 2) == 0) + { + nmask = 0xFF00 >> (4*n); + if ((nmask & l_data) == nmask) // entire byte bad + { + disable1_data |= (0xF0 >> (n*2)); + } + } + if (((nmask & l_data)>>(4*(3-n))) == 0x0F) + { + wrclk_mask |= wrclk_disable_mask[n]; } } } + FAPI_DBG("\t\tdisable1_data=0x%04X", disable1_data); + + // set disable0(dq) reg l_ecmdRc = data_buffer.setHalfWord(3, l_data); if (l_ecmdRc != ECMD_DBUF_SUCCESS) { @@ -3343,48 +3340,53 @@ fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) "Rank%i \tdp18_%i addr=0x%llx, data=0x%04X", port, dimm, prank, prg[prank][port], i, l_addr , l_data); -// rc = fapiPutScom(mba_target, l_addr, data_buffer); - rc = fapiPutScomUnderMask(mba_target, l_addr, data_buffer, data_buffer); + rc = fapiPutScomUnderMask(mba_target, l_addr, data_buffer, + data_buffer); if (rc) { FAPI_ERR("Error from fapiPutScom writing disable0 reg"); return rc; } + + // set address for disable1(dqs) register + l_addr += l_disable1_addr_offset; + if (disable1_data != 0) + { + l_ecmdRc = data_buffer.flushTo0(); // clear buffer + if (l_ecmdRc != ECMD_DBUF_SUCCESS) + { + FAPI_ERR("Error from ecmdDataBuffer flushTo0() " + "- rc 0x%.8X", l_ecmdRc); - if (l_dram_width == 4) { - uint16_t bn_mask = 0xF000; - uint16_t mask; - for (uint8_t q=0; q < 4; q++) { - mask = bn_mask >> (4*q); - if ((l_data & mask) == mask) { - disable1_data |= disable1_mask_lookup[aport][i][q]; - if ( !l_disable1_fixed ) { - wrclk_mask |= wrclk_disable_mask[q]; - } - FAPI_DBG("x4 disable1_data=0x%04X, wrclk_mask=0x%04X",disable1_data,wrclk_mask); - } + rc.setEcmdError(l_ecmdRc); + return rc; } - } else { - uint16_t bn_mask = 0xFF00; - uint16_t mask; - for (uint8_t q=0; q < 4; q=q+2) { - mask = bn_mask >> (4*q); - if ((l_data & mask) == mask) { - disable1_data |= disable1_mask_lookup[aport][i][q] | - disable1_mask_lookup[aport][i][q+1]; - if ( !l_disable1_fixed ) { - wrclk_mask |= wrclk_disable_mask[q] | wrclk_disable_mask[q+1]; - } - FAPI_DBG("x8 disable1_data=0x%04X, wrclk_mask=0x%04X",disable1_data,wrclk_mask); - } + + l_ecmdRc = data_buffer.setByte(6, disable1_data); + if (l_ecmdRc != ECMD_DBUF_SUCCESS) + { + FAPI_ERR("Error from ecmdDataBuffer setByte() " + "- rc 0x%.8X", l_ecmdRc); + + rc.setEcmdError(l_ecmdRc); + return rc; } - } - if (disable1_data != 0) { - // shift over 8 bits since disable1_lookup is 8 bits, and reg is 16 - disable1_data = disable1_data << 8; - l_addr += l_disable1_addr_offset; // set address for disable1 reg + // write disable1(dqs) register + rc = fapiPutScomUnderMask(mba_target, l_addr, + data_buffer, data_buffer); + if (rc) + { + FAPI_ERR("Error from PutScom writing disable1 reg"); + return rc; + } + } // end disable1_data != 0 + // set address for wrclk_en register + l_addr &= l_wrclk_en_addr_mask; + + if (wrclk_mask != 0) + { l_ecmdRc = data_buffer.flushTo0(); // clear buffer if (l_ecmdRc != ECMD_DBUF_SUCCESS) { @@ -3394,60 +3396,47 @@ fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) rc.setEcmdError(l_ecmdRc); return rc; } - - l_ecmdRc = data_buffer.setHalfWord(3, disable1_data); + ecmdDataBufferBase put_mask(64); + l_ecmdRc = put_mask.setHalfWord(3, wrclk_mask); if (l_ecmdRc != ECMD_DBUF_SUCCESS) { - FAPI_ERR("Error from ecmdDataBuffer setHalfWord() " - "- rc 0x%.8X", l_ecmdRc); + FAPI_ERR("Error from ecmdDataBuffer setHalfWord()" + " for wrclk_mask - rc 0x%.8X", l_ecmdRc); rc.setEcmdError(l_ecmdRc); return rc; } - // write disable1 register -// rc = fapiPutScom(mba_target, l_addr, data_buffer); - rc = fapiPutScomUnderMask(mba_target, l_addr, data_buffer, data_buffer); - if (rc) + if (!l_disable1_fixed) { - FAPI_ERR("Error from fapiPutScom writing disable1 reg"); - return rc; - } - -// for DD1.X chips since disable1 register not fully working... can take out wrclk stuff for DD2+ - if ( !l_disable1_fixed ) - { - l_addr &= l_wrclk_en_addr_mask; // set address for wrclk_en register - - l_ecmdRc = data_buffer.flushTo0(); // clear buffer - if (l_ecmdRc != ECMD_DBUF_SUCCESS) - { - FAPI_ERR("Error from ecmdDataBuffer flushTo0() " - "- rc 0x%.8X", l_ecmdRc); - - rc.setEcmdError(l_ecmdRc); - return rc; - } - - ecmdDataBufferBase put_mask(64); - l_ecmdRc = put_mask.setHalfWord(3, wrclk_mask); - if (l_ecmdRc != ECMD_DBUF_SUCCESS) + // clear(0) out the unused quads for wrclk + rc = fapiPutScomUnderMask(mba_target, l_addr, + data_buffer, put_mask); + if (rc) { - FAPI_ERR("Error from ecmdDataBuffer setHalfWord() for wrclk_mask" - "- rc 0x%.8X", l_ecmdRc); - - rc.setEcmdError(l_ecmdRc); - return rc; + FAPI_ERR("Error from fapiPutScomUnderMask writing " + "wrclk_en reg"); + return rc; } - // clear(0) out the unused quads - rc = fapiPutScomUnderMask(mba_target, l_addr, data_buffer, put_mask); + } + else + { + uint64_t rdclk_addr = + disable_reg[port][prank][i] & 0xFFFFFF040FFFFFFFull; + // clear(0) out the unused quads for rdclk + rc = fapiPutScomUnderMask(mba_target, rdclk_addr, + data_buffer, put_mask); if (rc) { - FAPI_ERR("Error from fapiPutScomUnderMask writing wrclk_en reg"); + FAPI_ERR("Error from fapiPutScomUnderMask writing " + "rdclk_en reg"); return rc; } - } // if not disable1_fixed - } // if disable1 data != 0 + + FAPI_DBG("rdclk_addr=0x%llx, wrclk_addr=0x%llx, " + "wrclk_mask=0x%04X", rdclk_addr, l_addr, wrclk_mask); + } + } // end wrclk_mask != 0 } // end DP18 instance loop } // end primary rank loop } // end port loop @@ -3455,6 +3444,56 @@ fapi::ReturnCode mss_set_bbm_regs (const fapi::Target & mba_target) } // end mss_set_bbm_regs +fapi::ReturnCode mss_get_dqs_lane (const fapi::Target & i_mba, + const uint8_t i_port, const uint8_t i_block, const uint8_t i_quad, + uint8_t &o_lane) +{ +// input = mba, port, dp18 block, quad +// output = OR'd in lane of the dqs for the specified input + + ReturnCode rc; + uint8_t dq, dqs; + uint8_t phy_lane = i_quad * 4; + uint8_t l_block = i_block; + // returns dq + rc=mss_c4_phy(i_mba,i_port,0,RD_DQ,dq,0,phy_lane,l_block,1); + if (rc) return rc; + dqs = dq / 4; + // returns phy_lane + rc=mss_c4_phy(i_mba,i_port,0,WR_DQS,dqs,0,phy_lane,l_block,0); + if (rc) return rc; + if (l_block != i_block) + { + FAPI_ERR("\t !!! blocks don't match from c4 to phy i_block=%i," + " o_block=%i", i_block, l_block); + } + + switch (phy_lane) + { + case 16: + case 17: + o_lane |= 0xC0; + break; + case 18: + case 19: + o_lane |= 0x30; + break; + case 20: + case 21: + o_lane |= 0x0C; + break; + case 22: + case 23: + o_lane |= 0x03; + break; + default: + FAPI_ERR("\t!!! (Port%i, dp18_%i, q=%i) phy_lane(%i)" + "returned from mss_c4_phy is invalid", + i_port, i_block, i_quad, phy_lane); +// FAPI_SET_HWP_ERROR(rc, RC_MSS_IMP_INPUT_ERROR); + } + return rc; +} //end mss_get_dqs_lane fapi::ReturnCode mss_get_bbm_regs (const fapi::Target & mba_target) { @@ -3527,21 +3566,17 @@ fapi::ReturnCode mss_get_bbm_regs (const fapi::Target & mba_target) ecmdDataBufferBase data_buffer(64); ecmdDataBufferBase db_reg(BITS_PER_PORT); uint32_t l_ecmdRc = ECMD_DBUF_SUCCESS; - uint8_t prg[MAX_PRI_RANKS][MAX_PORTS]; // primary rank group values + uint8_t prg[MAX_PRI_RANKS][MAX_PORTS]; // primary rank group values uint8_t l_dram_width; - FAPI_INF("Running set bad bits FN:mss_set_bbm_regs \n" - " input Target: %s", mba_target.toEcmdString()); + FAPI_INF("Running (get)registers->flash"); std::vector mba_dimms; fapiGetAssociatedDimms(mba_target, mba_dimms); // functional dimms - FAPI_INF("***-------- Found %i functional DIMMS --------***", - mba_dimms.size()); - // 4 dimms per MBA, 2 per port - - // ATTR_EFF_PRIMARY_RANK_GROUP0[port], GROUP1[port], GROUP2[port], GROUP3[port] + // ATTR_EFF_PRIMARY_RANK_GROUP0[port], GROUP1[port], + // GROUP2[port], GROUP3[port] rc=FAPI_ATTR_GET(ATTR_EFF_PRIMARY_RANK_GROUP0, &mba_target, prg[0]); if(rc) return rc; rc=FAPI_ATTR_GET(ATTR_EFF_PRIMARY_RANK_GROUP1, &mba_target, prg[1]); @@ -3591,17 +3626,29 @@ fapi::ReturnCode mss_get_bbm_regs (const fapi::Target & mba_target) uint8_t dimm = prg[prank][port] >> 2; uint8_t rank = prg[prank][port] & 0x03; uint16_t l_data = 0; + uint8_t l_has_bad_bits = 0; if (prg[prank][port] == rg_invalid[prank]) // invalid rank { - FAPI_INF("Primary rank group %i is INVALID, continuing...", + FAPI_DBG("Primary rank group %i is INVALID, continuing...", prank); continue; } - for ( uint8_t i=0; i < DP18_INSTANCES; i++ ) // dp18 [0:4] + // create the db_reg (all the failed bits of the port) + l_ecmdRc = db_reg.flushTo0(); + if (l_ecmdRc != ECMD_DBUF_SUCCESS) { + FAPI_ERR("Error from ecmdDataBuffer flushTo0() " + "- rc 0x%.8X", l_ecmdRc); + + rc.setEcmdError(l_ecmdRc); + return rc; + } + FAPI_DBG("Port%i, dimm=%i, prg%i rank=%i", port, dimm, prank, rank); + for ( uint8_t i=0; i < DP18_INSTANCES; i++ ) // dp18 [0:4] + { // clear bits 48:63 l_ecmdRc = data_buffer.clearBit(48, BITS_PER_REG); if (l_ecmdRc != ECMD_DBUF_SUCCESS) @@ -3622,238 +3669,310 @@ fapi::ReturnCode mss_get_bbm_regs (const fapi::Target & mba_target) } l_data = data_buffer.getHalfWord(3); - if (l_ecmdRc != ECMD_DBUF_SUCCESS) - { - FAPI_ERR("Error from ecmdDataBuffer setHalfWord() " - "- rc 0x%.8X", l_ecmdRc); - rc.setEcmdError(l_ecmdRc); - return rc; - } + FAPI_DBG("dp18_%i 0x%llx = 0x%x", i, + disable_reg[port][prank][i], l_data); - if (l_dram_width == 4) { // disable entire nibble if bad bit found - uint16_t mask = 0xF000; - for (uint8_t n=0; n < 4; n++) { // check each nibble - uint16_t nmask = mask >> (4*n); - if ((nmask & l_data) > 0) { - l_data = l_data | nmask; - FAPI_INF("Disabling nibble %i",n); + if (l_data != 0) + { + l_has_bad_bits = 1; + // to complement Marc Gollub's request in mss_set_bbm_regs + // and stay consistent for procedures following this one + // if x4 and any bit in a nibble is bad, mask entire nibble + if (l_dram_width == 4) { + uint16_t mask = 0xF000; + for (uint8_t n=0; n < 4; n++) { // check each nibble + uint16_t nmask = mask >> (4*n); + if ((nmask & l_data) > 0) { + l_data = l_data | nmask; + FAPI_INF("Disabling entire nibble %i",n); + } } } - } - l_ecmdRc |= db_reg.setHalfWord(i, l_data); - if (l_ecmdRc != ECMD_DBUF_SUCCESS) - { - FAPI_ERR("Error from ecmdDataBuffer setHalfWord() " + l_ecmdRc = db_reg.setHalfWord(i, l_data); + if (l_ecmdRc != ECMD_DBUF_SUCCESS) + { + FAPI_ERR("Error from ecmdDataBuffer setHalfWord() " "- rc 0x%.8X", l_ecmdRc); - rc.setEcmdError(l_ecmdRc); - return rc; - } - - FAPI_INF("+++ Setting Bad Bit Mask p%i: DIMM%i PRG%i " - "Rank%i \tdp18_%i addr=0x%llx, data=0x%04X", port, - dimm, prank, prg[prank][port], i, - disable_reg[port][prank][i], l_data); + rc.setEcmdError(l_ecmdRc); + return rc; + } + FAPI_INF("+++ Setting Bad Bit Mask p%i: DIMM%i PRG%i " + "Rank%i \tdp18_%i addr=0x%llx, data=0x%04X", port, + dimm, prank, prg[prank][port], i, + disable_reg[port][prank][i], l_data); + } } // end DP18 instance loop - rc = setC4dq2reg(mba_target, port, dimm, rank, db_reg); - if (rc) + if (l_has_bad_bits) { - FAPI_ERR("Error from setting register bitmap p%i: " + rc = setC4dq2reg(mba_target, port, dimm, rank, db_reg); + if (rc) + { + FAPI_ERR("Error from setting register bitmap p%i: " "dimm=%i, rank=%i rc=%i", port, dimm, rank, static_cast(rc)); - return rc; + return rc; + } } - } // end primary rank loop } // end port loop return rc; } // end mss_get_bbm_regs -// output reg = in phy based order -ReturnCode getC4dq2reg(const Target & i_mba, const uint8_t i_port, const uint8_t i_dimm, const uint8_t i_rank, ecmdDataBufferBase &o_reg) +ReturnCode getC4dq2reg(const Target & i_mba, const uint8_t i_port, + const uint8_t i_dimm, const uint8_t i_rank, ecmdDataBufferBase &o_reg, uint8_t &is_clean) { - // [port][bits per port] - const uint8_t lookup[4][BITS_PER_PORT] = { - // port 0 - {65,66,67,64, 70,69,68,71, 21,20,23,22, 18,16,19,17, // DP18 block 0 - 61,63,60,62, 57,58,59,56, 73,74,75,72, 78,77,79,76, // ... block 1 - 7, 5, 4, 6, 0, 2, 1, 3, 12,13,15,14, 10, 8,11, 9, // ... block 2 - 47,44,46,45, 43,42,41,40, 31,29,30,28, 26,24,27,25, // ... block 3 - 55,53,54,52, 50,48,49,51, 33,34,35,32, 36,37,38,39}, // ... block 4 - // port 1 - {17,16,18,19, 20,21,22,23, 2, 0, 3, 1, 7, 4, 5, 6, - 70,71,69,68, 66,64,67,65, 27,24,26,25, 29,30,31,28, - 37,36,38,39, 35,32,34,33, 77,76,79,78, 73,75,72,74, - 40,42,41,43, 45,44,46,47, 9,11, 8,10, 12,13,14,15, - 48,51,49,50, 52,53,54,55, 61,63,62,60, 56,58,59,57}, - // port 2 - {22,23,20,21, 19,16,17,18, 26,25,24,27, 29,28,31,30, - 67,64,65,66, 71,70,69,68, 7, 5, 6, 4, 2, 0, 3, 1, - 45,44,47,46, 42,43,41,40, 39,38,37,36, 33,34,35,32, - 48,50,49,51, 54,52,53,55, 15,13,12,14, 9, 8,10,11, - 61,60,62,63, 59,56,58,57, 74,72,73,75, 76,79,78,77}, - // port 3 - {25,26,27,24, 28,31,29,30, 17,19,16,18, 20,21,23,22, - 64,67,66,65, 71,69,68,70, 75,74,72,73, 76,77,79,78, - 4, 5, 7, 6, 0, 1, 2, 3, 12,13,14,15, 8, 9,11,10, - 47,45,46,44, 43,41,42,40, 35,32,33,34, 39,37,36,38, - 55,52,53,54, 51,48,49,50, 60,62,61,63, 57,59,56,58} - }; +// used by set_bbm(flash to registers) +// calls dimmGetBadDqBitmap and converts the data to phy order in a databuffer +// output reg = in phy based order(lanes) uint8_t l_bbm[TOTAL_BYTES] = {0}; // bad bitmap from dimmGetBadDqBitmap - ecmdDataBufferBase c4dqbmp(BITS_PER_PORT); // databuffer of C4 dq bitmap ReturnCode rc; - uint8_t l_port = i_port; // port # relative to Centaur - uint8_t mba_pos = 0; uint32_t ecmdrc = ECMD_DBUF_SUCCESS; + uint8_t dq; + uint8_t phy_lane, phy_block; ecmdrc = o_reg.flushTo0(); // clear output databuffer if (ecmdrc != ECMD_DBUF_SUCCESS) { - FAPI_ERR("Error from ecmdDataBuffer flushTo0() " - "- rc 0x%.8X", ecmdrc); + FAPI_ERR("Error from ecmdDataBuffer flushTo0() " + "- rc 0x%.8X", ecmdrc); - rc.setEcmdError(ecmdrc); - return rc; - } - rc=FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_mba, mba_pos); - if (rc) - { - FAPI_ERR("Error getting ATTR_CHIP_UNIT_POS for MBA"); - return (rc); + rc.setEcmdError(ecmdrc); + return rc; } // get Centaur dq bitmap (C4 signal) order=[0:79], array of bytes rc = dimmGetBadDqBitmap(i_mba, i_port, i_dimm, i_rank, l_bbm); if (rc) { - FAPI_ERR("Error from dimmGetBadDqBitmap on MBA%ip%i: " - "dimm=%i, rank=%i rc=%i", mba_pos, i_port, i_dimm, i_rank, - static_cast(rc)); - return rc; + FAPI_ERR("Error from dimmGetBadDqBitmap on port %i: " + "dimm=%i, rank=%i rc=%i", i_port, i_dimm, i_rank, + static_cast(rc)); + return rc; } - // create databuffer from C4 dq bitmap array - ecmdrc = c4dqbmp.insertFromRight(l_bbm, 0, BITS_PER_PORT); - if (ecmdrc != ECMD_DBUF_SUCCESS) - { - FAPI_ERR("Error from ecmdDataBuffer insertFromRight() " - "- rc 0x%.8X", ecmdrc); + uint8_t dimm_spare[MAX_PORTS][MAX_DIMMS][MAX_PRI_RANKS]; + rc = FAPI_ATTR_GET(ATTR_VPD_DIMM_SPARE, &i_mba, dimm_spare); + if(rc) return rc; - rc.setEcmdError(ecmdrc); - return rc; - } + for (uint8_t byte=0; byte < TOTAL_BYTES; byte++) + { + if (l_bbm[byte] != 0) + { + if (byte == (TOTAL_BYTES-1)) // spare byte + { + uint8_t spare_bitmap = 0; + + switch (dimm_spare[i_port][i_dimm][i_rank]) + { + case ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE: + spare_bitmap = 0; + break; + case ENUM_ATTR_VPD_DIMM_SPARE_LOW_NIBBLE: + spare_bitmap = 0x0F; + break; + case ENUM_ATTR_VPD_DIMM_SPARE_HIGH_NIBBLE: + spare_bitmap = 0xF0; + break; + case ENUM_ATTR_VPD_DIMM_SPARE_FULL_BYTE: + spare_bitmap = 0xFF; + break; + default: + FAPI_ERR("ATTR_VPD_DIMM_SPARE is invalid %u", + dimm_spare[i_port][i_dimm][i_rank]); + FAPI_SET_HWP_ERROR(rc, RC_MSS_IMP_INPUT_ERROR); + return rc; + } - // quick check if there no bits on, we're done - if (c4dqbmp.getNumBitsSet(0, BITS_PER_PORT) == 0) - { - return rc; - } - l_port = i_port + (mba_pos * MAX_PORTS); // relative to Centaur + if (l_bbm[byte] == spare_bitmap) // spare already set via initfile + continue; + } - for (uint8_t i=0; i < BITS_PER_PORT; i++) - { - if (c4dqbmp.isBitSet(lookup[l_port][i])) - { - o_reg.setBit(i); - FAPI_DBG("set bad bit C4_dq=%i,\t dp18_%i_lane%i\t (bit %i)", - lookup[l_port][i], (i / 16), (i % 16), i); - } - } + uint8_t bs=0; + uint8_t be=8; + uint8_t loc=0; + is_clean = 0; - return rc; -} + if ((l_bbm[byte] & 0xF0) == 0xF0) // 0xF? + { + dq = (byte * 8); // for first lane + // input=cen_c4_dq, output=phy block, lane + rc = mss_c4_phy(i_mba, i_port, 0, RD_DQ,dq, + 0, phy_lane,phy_block, 0); + if (rc) return rc; + + if (l_bbm[byte] == 0xFF) + { // block lanes + 1st lane{0,8} + loc = (phy_block * 16) + (phy_lane & 0x08); + o_reg.setBit(loc, 8); // set dq byte + FAPI_DBG("0xFF byte=%i, lbbm=0x%02x dp%i_%i dq=%i o=%i", + byte, l_bbm[byte], phy_block, phy_lane, dq, loc); + continue; + } + // block lanes + 1st lane{0,4,8,12} + loc = (phy_block * 16) + (phy_lane & 0x0C); + o_reg.setBit(loc, 4); // set dq nibble0 + FAPI_DBG("0xF0 byte=%i, lbbm=0x%02x dp%i_%i dq=%i o=%i", + byte, l_bbm[byte], phy_block, phy_lane, dq, loc); -ReturnCode setC4dq2reg(const Target &i_mba, const uint8_t i_port, const uint8_t i_dimm, const uint8_t i_rank, ecmdDataBufferBase &o_reg) + if (l_bbm[byte] == 0xF0) // done with byte + continue; + bs=4; // processed the first 4 bits already + } + else if ((l_bbm[byte] & 0x0F) == 0x0F) // 0x?F + { + dq = (byte * 8) + 4; // for first lane of dq + rc = mss_c4_phy(i_mba, i_port, 0, RD_DQ,dq, + 0, phy_lane, phy_block, 0); + if (rc) return rc; + // block lanes + 1st lane{0,4,8,12} + loc = (phy_block * 16) + (phy_lane & 0x0C); + FAPI_DBG("0x0F byte=%i, lbbm=0x%02x dp%i_%i dq=%i o=%i", + byte, l_bbm[byte], phy_block, phy_lane, dq, loc); + o_reg.setBit(loc, 4); // set dq nibble1 + if (l_bbm[byte] == 0x0F) // done with byte + continue; + be=4; // processed the last 4 bits already + } + else if ((l_bbm[byte] >> 4) == 0) // 0x0? + bs=4; + else if ((l_bbm[byte] & 0x0F) == 0) // 0x?0 + be=4; + + for (uint8_t b=bs; b < be; b++) // test each bit + { + if ((l_bbm[byte] & (0x80 >> b)) > 0) // bit is set, + { + dq = (byte * 8) + b; + rc=mss_c4_phy(i_mba, i_port, 0, RD_DQ,dq, + 0, phy_lane, phy_block, 0); + if (rc) return rc; + loc = (phy_block * 16) + phy_lane; + o_reg.setBit(loc); + FAPI_DBG("b=%i byte=%i, lbbm=0x%02x dp%i_%i dq=%i " + "loc=%i bs=%i be=%i", b, byte, l_bbm[byte], + phy_block, phy_lane, dq, loc, bs, be); + } + } + } // end if not clean + } // end byte + return rc; +} // end getC4dq2reg + + +ReturnCode setC4dq2reg(const Target &i_mba, const uint8_t i_port, + const uint8_t i_dimm, const uint8_t i_rank, const ecmdDataBufferBase &i_reg) { +// used by get_bbm(registers to flash) +// Converts the data from phy order (i_reg) to cen_c4_dq array +// for dimmSetBadDqBitmap to write flash with - const uint8_t lookup[4][BITS_PER_PORT] = { - // port 0 - {65,66,67,64,70,69,68,71,21,20,23,22,18,16,19,17, // DP18 block 0 - 61,63,60,62,57,58,59,56,73,74,75,72,78,77,79,76, // ... block 1 - 7, 5, 4, 6, 0, 2, 1, 3,12,13,15,14,10, 8,11, 9, // ... block 2 - 47,44,46,45,43,42,41,40,31,29,30,28,26,24,27,25, // ... block 3 - 55,53,54,52,50,48,49,51,33,34,35,32,36,37,38,39}, // ... block 4 - // port 1 - {17,16,18,19,20,21,22,23, 2, 0, 3, 1, 7, 4, 5, 6, - 70,71,69,68,66,64,67,65,27,24,26,25,29,30,31,28, - 37,36,38,39,35,32,34,33,77,76,79,78,73,75,72,74, - 40,42,41,43,45,44,46,47, 9,11, 8,10,12,13,14,15, - 48,51,49,50,52,53,54,55,61,63,62,60,56,58,59,57}, - // port 2 - {22,23,20,21,19,16,17,18,26,25,24,27,29,28,31,30, - 67,64,65,66,71,70,69,68, 7, 5, 6, 4, 2, 0, 3, 1, - 45,44,47,46,42,43,41,40,39,38,37,36,33,34,35,32, - 48,50,49,51,54,52,53,55,15,13,12,14, 9, 8,10,11, - 61,60,62,63,59,56,58,57,74,72,73,75,76,79,78,77}, - // port 3 - {25,26,27,24,28,31,29,30,17,19,16,18,20,21,23,22, - 64,67,66,65,71,69,68,70,75,74,72,73,76,77,79,78, - 4, 5, 7, 6, 0, 1, 2, 3,12,13,14,15, 8, 9,11,10, - 47,45,46,44,43,41,42,40,35,32,33,34,39,37,36,38, - 55,52,53,54,51,48,49,50,60,62,61,63,57,59,56,58} - }; - uint8_t l_bbm [TOTAL_BYTES] = {0}; - ecmdDataBufferBase c4dqbmp(BITS_PER_PORT); ReturnCode rc; - uint8_t l_port = i_port; - uint8_t mba_pos = 0; - uint32_t ecmdrc = ECMD_DBUF_SUCCESS; + uint8_t l_bbm [TOTAL_BYTES] = {0}; + uint8_t dq=0; + uint8_t phy_lane; + uint8_t phy_block; + uint8_t data; + + // get Centaur dq bitmap (C4 signal) order=[0:79], array of bytes + rc = dimmGetBadDqBitmap(i_mba, i_port, i_dimm, i_rank, l_bbm); + if (rc) + { + FAPI_ERR("Error from dimmGetBadDqBitmap on port %i: " + "dimm=%i, rank=%i rc=%i", i_port, i_dimm, i_rank, + static_cast(rc)); + return rc; + } - // clear output databuffer - ecmdrc = c4dqbmp.flushTo0(); - if (ecmdrc != ECMD_DBUF_SUCCESS) + for (uint8_t byte=0; byte < TOTAL_BYTES; byte++) { - FAPI_ERR("Error from ecmdDataBuffer flushTo0() " - "- rc 0x%.8X", ecmdrc); + data = i_reg.getByte(byte); + if (data != 0) // need to check bits + { + uint8_t bs=0; + uint8_t be=8; - rc.setEcmdError(ecmdrc); - return rc; - } + phy_block = (byte / 2); // byte=[0..9], block=[0..4] + FAPI_DBG("\n\t\t\t\t\t\tbyte=%i, data=0x%02x phy_block=%i ", + byte, data, phy_block); + if ((data & 0xF0) == 0xF0) // 0xF? + { + phy_lane = 8 * (byte % 2); // lane=[0,8] + // input=block, lane output=cen_dq + rc = mss_c4_phy(i_mba, i_port, 0, RD_DQ,dq, + 0, phy_lane, phy_block, 1); + if (rc) return rc; + + if (data == 0xFF) + { // set 8 consecutive bits of the cen_c4_dq + l_bbm[(dq/8)] = 0xFF; + FAPI_DBG("0xFF dp%i_%i dq=%i, lbbm=0x%02x", + phy_block, phy_lane, dq, l_bbm[dq/8]); + continue; + } - // Set Port info - rc=FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_mba, mba_pos); - if (rc) - { - FAPI_ERR("Error getting ATTR_CHIP_UNIT_POS for MBA"); - return (rc); - } + l_bbm[(dq/8)] |= ((dq % 8) < 4) ? 0xF0 : 0x0F; + FAPI_DBG("0xF0 dp%i_%i dq=%i, lbbm=0x%02x", + phy_block, phy_lane, dq, l_bbm[dq/8]); - l_port = i_port + (mba_pos * MAX_PORTS); + if (data == 0xF0) // done with byte + continue; + bs=4; // need to work on other bits + } + else if ((data & 0x0F) == 0x0F) // 0x?F + { + phy_lane = (8 * (byte % 2)) + 4; // lane=[4,12] + rc = mss_c4_phy(i_mba, i_port, 0, RD_DQ, dq, + 0, phy_lane, phy_block, 1); + if (rc) return rc; - // translate c4 from input - for (uint8_t i=0; i < BITS_PER_PORT; i++) - { - if (o_reg.isBitSet(i)) - { - c4dqbmp.setBit(lookup[l_port][i]); - } - } + l_bbm[(dq/8)] |= ((dq % 8) < 4) ? 0xF0 : 0x0F; + FAPI_DBG("0x0F dp%i_%i dq=%i, lbbm=0x%02x", + phy_block, phy_lane, dq, l_bbm[dq/8]); - // create array from databuffer - for (uint8_t b=0; b < TOTAL_BYTES; b++) - { - l_bbm[b] = c4dqbmp.getByte(b); - } + if (data == 0x0F) // done with byte + continue; + be=4; // need to work on other bits + } + else if ((data >> 4) == 0) // 0x0? + bs=4; + else if ((data & 0x0F) == 0) // 0x?0 + be=4; + + for (uint8_t b=bs; b < be; b++) // test each bit + { + if ((data & (0x80 >> b)) > 0) // bit is set, + { + phy_lane = (8 * (byte % 2)) + b; + rc = mss_c4_phy(i_mba, i_port, 0, RD_DQ, dq, + 0, phy_lane, phy_block, 1); + if (rc) return rc; + l_bbm[(dq/8)] |= (0x80 >> (dq % 8)); + FAPI_DBG("b=%i dp%i_%i dq=%i, lbbm=0x%02x", + b, phy_block, phy_lane, dq, l_bbm[dq/8]); + } + } + } //end if not clean + } //end byte // set Centaur dq bitmap (C4 signal) order=[0:79], array of bytes rc = dimmSetBadDqBitmap(i_mba, i_port, i_dimm, i_rank, l_bbm); if (rc) { - FAPI_ERR("Error from dimmSetBadDqBitmap on MBA%ip%i: " - "dimm=%i, rank=%i rc=%i", mba_pos, i_port, i_dimm, i_rank, - static_cast(rc)); + FAPI_ERR("Error from dimmSetBadDqBitmap on port %i: " + "dimm=%i, rank=%i rc=%i", i_port, i_dimm, i_rank, + static_cast(rc)); return rc; } return rc; -} +} //end setC4dq2reg } //end extern C - -- cgit v1.2.1