@@ -881,6 +881,247 @@ fapi_try_exit:
881
881
return fapi2 ::current_err ;
882
882
}
883
883
884
+ ///
885
+ /// @brief PMIC power down sequence for 1U/2U parts
886
+ ///
887
+ /// @param[in] i_target OCMB target
888
+ /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code
889
+ ///
890
+ fapi2 ::ReturnCode power_down_sequence_1u_2u (const fapi2 ::Target < fapi2 ::TARGET_TYPE_OCMB_CHIP > & i_target )
891
+ {
892
+ using REGS = pmicRegs < mss ::pmic ::product ::JEDEC_COMPLIANT > ;
893
+ using FIELDS = pmicFields < mss ::pmic ::product ::JEDEC_COMPLIANT > ;
894
+
895
+ fapi2 ::ReturnCode l_rc = fapi2 ::FAPI2_RC_SUCCESS ;
896
+
897
+ auto l_pmics = mss ::find_targets_sorted_by_pos < fapi2 ::TARGET_TYPE_PMIC > (i_target );
898
+
899
+ // Next, sort them by the sequence attributes
900
+ FAPI_TRY (mss ::pmic ::order_pmics_by_sequence (i_target , l_pmics ));
901
+
902
+ // Reverse loop, so we disable in the opposite order as the enable
903
+ for (int16_t l_i = (l_pmics .size () - 1 ); l_i >= 0 ; -- l_i )
904
+ {
905
+ const auto& PMIC = l_pmics [l_i ];
906
+ fapi2 ::buffer < uint8_t > l_reg_contents ;
907
+
908
+ // Redundant clearBit, but just so it's clear what we're doing
909
+ FAPI_TRY (mss ::pmic ::i2c ::reg_read_reverse_buffer (PMIC , REGS ::R32 , l_reg_contents ));
910
+ l_reg_contents .clearBit < FIELDS ::R32_VR_ENABLE > ();
911
+
912
+ // Due to long soft stop time in 4U (~8ms), let's delay for 10ms to be safe
913
+ fapi2 ::delay (10 * mss ::common_timings ::DELAY_1MS , mss ::common_timings ::DELAY_1MS );
914
+
915
+ // We are opting here to log RC's here as recovered. If this register write fails,
916
+ // the ones later in the procedure will fail as well.
917
+ l_rc = mss ::pmic ::i2c ::reg_write_reverse_buffer (PMIC , REGS ::R32 , l_reg_contents );
918
+
919
+ if (l_rc != fapi2 ::FAPI2_RC_SUCCESS )
920
+ {
921
+ fapi2 ::logError (l_rc , fapi2 ::FAPI2_ERRL_SEV_RECOVERED );
922
+ fapi2 ::current_err = fapi2 ::FAPI2_RC_SUCCESS ;
923
+ }
924
+
925
+ }
926
+
927
+ fapi_try_exit :
928
+ return fapi2 ::current_err ;
929
+ }
930
+
931
+ ///
932
+ /// @brief PMIC power down sequence for 4U parts for pmic
933
+ ///
934
+ /// @param[in,out] io_target_info Target info struct
935
+ /// @return fapi2::ReturnCode
936
+ ///
937
+ fapi2 ::ReturnCode pmic_clear_vr_swa_swc_en (target_info_redundancy & io_target_info )
938
+ {
939
+ using REGS = pmicRegs < mss ::pmic ::product ::JEDEC_COMPLIANT > ;
940
+ using FIELDS = pmicFields < mss ::pmic ::product ::JEDEC_COMPLIANT > ;
941
+
942
+ // Regardless of the N-Mode states, we want to try to do a full disable of all parts
943
+ // so if we do hit a failure on a PMIC write, we will just continue. enable_with_redundancy
944
+ // on the next run of pmic_enable should catch read/write failures and handle them correctly
945
+ // with the correct N-Mode declaration logic
946
+
947
+ // These PMIC writes have the potential to fail in N-Mode configs. We will not do any
948
+ // N-mode declarations here as the runtime detection or next enable will catch all of these.
949
+ FAPI_TRY_NO_TRACE (run_if_present (io_target_info .iv_pmic_map , mss ::pmic ::id ::PMIC3 , []
950
+ (const fapi2 ::Target < fapi2 ::TARGET_TYPE_PMIC > & i_pmic ) -> fapi2 ::ReturnCode
951
+ {
952
+ fapi2 ::buffer < uint8_t > l_reg_contents ;
953
+
954
+ // VR Disable PMIC3
955
+ mss ::pmic ::i2c ::reg_read_reverse_buffer (i_pmic , REGS ::R32 , l_reg_contents );
956
+ l_reg_contents .clearBit < FIELDS ::R32_VR_ENABLE > ();
957
+
958
+ mss ::pmic ::i2c ::reg_write_reverse_buffer (i_pmic , REGS ::R32 , l_reg_contents );
959
+
960
+ return fapi2 ::FAPI2_RC_SUCCESS ;
961
+ }));
962
+
963
+ FAPI_TRY_NO_TRACE (run_if_present (io_target_info .iv_pmic_map , mss ::pmic ::id ::PMIC1 , []
964
+ (const fapi2 ::Target < fapi2 ::TARGET_TYPE_PMIC > & i_pmic ) -> fapi2 ::ReturnCode
965
+ {
966
+ fapi2 ::buffer < uint8_t > l_reg_contents ;
967
+
968
+ // VR Disable PMIC1
969
+ mss ::pmic ::i2c ::reg_read_reverse_buffer (i_pmic , REGS ::R32 , l_reg_contents );
970
+ l_reg_contents .clearBit < FIELDS ::R32_VR_ENABLE > ();
971
+
972
+ mss ::pmic ::i2c ::reg_write_reverse_buffer (i_pmic , REGS ::R32 , l_reg_contents );
973
+
974
+ return fapi2 ::FAPI2_RC_SUCCESS ;
975
+ }));
976
+
977
+ FAPI_TRY_NO_TRACE (run_if_present (io_target_info .iv_pmic_map , mss ::pmic ::id ::PMIC2 , []
978
+ (const fapi2 ::Target < fapi2 ::TARGET_TYPE_PMIC > & i_pmic ) -> fapi2 ::ReturnCode
979
+ {
980
+ fapi2 ::buffer < uint8_t > l_reg_contents ;
981
+
982
+ // Disable SWA and SWC of PMIC2
983
+ mss ::pmic ::i2c ::reg_read_reverse_buffer (i_pmic , REGS ::R2F , l_reg_contents );
984
+
985
+ l_reg_contents .clearBit < FIELDS ::R2F_SWA_REGULATOR_CONTROL > ();
986
+ l_reg_contents .clearBit < FIELDS ::R2F_SWC_REGULATOR_CONTROL > ();
987
+
988
+ mss ::pmic ::i2c ::reg_write_reverse_buffer (i_pmic , REGS ::R2F , l_reg_contents );
989
+
990
+ return fapi2 ::FAPI2_RC_SUCCESS ;
991
+ }));
992
+
993
+ FAPI_TRY_NO_TRACE (run_if_present (io_target_info .iv_pmic_map , mss ::pmic ::id ::PMIC0 , []
994
+ (const fapi2 ::Target < fapi2 ::TARGET_TYPE_PMIC > & i_pmic ) -> fapi2 ::ReturnCode
995
+ {
996
+ fapi2 ::buffer < uint8_t > l_reg_contents ;
997
+
998
+ // Disable SWA and SWC of PMIC0
999
+ mss ::pmic ::i2c ::reg_read_reverse_buffer (i_pmic , REGS ::R2F , l_reg_contents );
1000
+
1001
+ l_reg_contents .clearBit < FIELDS ::R2F_SWA_REGULATOR_CONTROL > ();
1002
+ l_reg_contents .clearBit < FIELDS ::R2F_SWC_REGULATOR_CONTROL > ();
1003
+
1004
+ mss ::pmic ::i2c ::reg_write_reverse_buffer (i_pmic , REGS ::R2F , l_reg_contents );
1005
+
1006
+ return fapi2 ::FAPI2_RC_SUCCESS ;
1007
+ }));
1008
+
1009
+ // Delay 700ms to allow more time for VDDR to ramp down before VPP ramps down.
1010
+ fapi2 ::delay (700 * mss ::common_timings ::DELAY_1MS , mss ::common_timings ::DELAY_1MS );
1011
+
1012
+ FAPI_TRY_NO_TRACE (run_if_present (io_target_info .iv_pmic_map , mss ::pmic ::id ::PMIC0 , []
1013
+ (const fapi2 ::Target < fapi2 ::TARGET_TYPE_PMIC > & i_pmic ) -> fapi2 ::ReturnCode
1014
+ {
1015
+ fapi2 ::buffer < uint8_t > l_reg_contents ;
1016
+
1017
+ // VR Disable
1018
+ mss ::pmic ::i2c ::reg_read_reverse_buffer (i_pmic , REGS ::R32 , l_reg_contents );
1019
+ l_reg_contents .clearBit < FIELDS ::R32_VR_ENABLE > ();
1020
+
1021
+ mss ::pmic ::i2c ::reg_write_reverse_buffer (i_pmic , REGS ::R32 , l_reg_contents );
1022
+
1023
+ return fapi2 ::FAPI2_RC_SUCCESS ;
1024
+ }));
1025
+
1026
+ FAPI_TRY_NO_TRACE (run_if_present (io_target_info .iv_pmic_map , mss ::pmic ::id ::PMIC2 , []
1027
+ (const fapi2 ::Target < fapi2 ::TARGET_TYPE_PMIC > & i_pmic ) -> fapi2 ::ReturnCode
1028
+ {
1029
+ fapi2 ::buffer < uint8_t > l_reg_contents ;
1030
+
1031
+ // VR Disable
1032
+ mss ::pmic ::i2c ::reg_read_reverse_buffer (i_pmic , REGS ::R32 , l_reg_contents );
1033
+ l_reg_contents .clearBit < FIELDS ::R32_VR_ENABLE > ();
1034
+
1035
+ mss ::pmic ::i2c ::reg_write_reverse_buffer (i_pmic , REGS ::R32 , l_reg_contents );
1036
+
1037
+ return fapi2 ::FAPI2_RC_SUCCESS ;
1038
+ }));
1039
+
1040
+ fapi2 ::current_err = fapi2 ::FAPI2_RC_SUCCESS ;
1041
+
1042
+ fapi_try_exit :
1043
+ return fapi2 ::current_err ;
1044
+ }
1045
+
1046
+ ///
1047
+ /// @brief PMIC power down sequence for 4U parts
1048
+ ///
1049
+ /// @param[in] i_target OCMB target
1050
+ /// @return fapi2::ReturnCode
1051
+ ///
1052
+ fapi2 ::ReturnCode power_down_sequence_4u (const fapi2 ::Target < fapi2 ::TARGET_TYPE_OCMB_CHIP > & i_target )
1053
+ {
1054
+ fapi2 ::ReturnCode l_rc = fapi2 ::FAPI2_RC_SUCCESS ;
1055
+
1056
+ const auto I2C_DEVICES =
1057
+ mss ::find_targets_sorted_by_pos < fapi2 ::TARGET_TYPE_GENERICI2CSLAVE > (i_target );
1058
+
1059
+ // Grab the targets as a struct, if they exist
1060
+ target_info_redundancy l_target_info (i_target , l_rc );
1061
+ // If platform did not provide a usable set of targets (4 GENERICI2CSLAVE, at least 2 PMICs),
1062
+ // Then we can't properly disable, the part is as good as dead, since re-enable would fail
1063
+ FAPI_TRY (l_rc , "Unusable PMIC/GENERICI2CSLAVE child target configuration found from %s" ,
1064
+ mss ::c_str (i_target ));
1065
+
1066
+ // ADC or GPIO fails are hard fails.
1067
+ // ADCs and GPIOs are guaranted to exist as asserted by l_rc above
1068
+ FAPI_TRY (mss ::pmic ::i2c ::reg_write (l_target_info .iv_adc1 , mss ::adc ::regs ::GENERAL_CFG ,
1069
+ mss ::adc ::fields ::GENERAL_CFG_CLEAR_STATS_EN ));
1070
+ FAPI_TRY (mss ::pmic ::i2c ::reg_write (l_target_info .iv_adc1 , mss ::adc ::regs ::SEQUENCE_CFG ,
1071
+ mss ::adc ::fields ::SEQUENCE_CFG_AUTO_SEQUENCE ));
1072
+
1073
+ FAPI_TRY (mss ::pmic ::i2c ::reg_write (l_target_info .iv_adc2 , mss ::adc ::regs ::GENERAL_CFG ,
1074
+ mss ::adc ::fields ::GENERAL_CFG_CLEAR_STATS_EN ));
1075
+ FAPI_TRY (mss ::pmic ::i2c ::reg_write (l_target_info .iv_adc2 , mss ::adc ::regs ::SEQUENCE_CFG ,
1076
+ mss ::adc ::fields ::SEQUENCE_CFG_AUTO_SEQUENCE ));
1077
+
1078
+ FAPI_TRY (pmic_clear_vr_swa_swc_en (l_target_info ));
1079
+
1080
+ // Finally, disable the GPIOs, and delay
1081
+ FAPI_TRY (mss ::pmic ::i2c ::reg_write (I2C_DEVICES [mss ::GPIO1 ], mss ::gpio ::regs ::EFUSE_OUTPUT ,
1082
+ mss ::gpio ::fields ::EFUSE_OUTPUT_OFF ));
1083
+ FAPI_TRY (mss ::pmic ::i2c ::reg_write (I2C_DEVICES [mss ::GPIO2 ], mss ::gpio ::regs ::EFUSE_OUTPUT ,
1084
+ mss ::gpio ::fields ::EFUSE_OUTPUT_OFF ));
1085
+
1086
+ // Delay 2 seconds. FW and cronus run pmic_enable in parallel. So the overall delay will only be 2 secs
1087
+ // across all the targets during IPL
1088
+ fapi2 ::delay (2000 * mss ::common_timings ::DELAY_1MS , mss ::common_timings ::DELAY_1MS );
1089
+
1090
+ fapi2 ::current_err = fapi2 ::FAPI2_RC_SUCCESS ;
1091
+
1092
+ fapi_try_exit :
1093
+ return fapi2 ::current_err ;
1094
+ }
1095
+
1096
+ ///
1097
+ /// @brief Power down function for 4U pmics
1098
+ /// @param[in] i_target ocmb target
1099
+ /// @return FAPI2_RC_SUCCESS iff ok
1100
+ ///
1101
+ fapi2 ::ReturnCode pmic_power_down (const fapi2 ::Target < fapi2 ::TARGET_TYPE_OCMB_CHIP > & i_target )
1102
+ {
1103
+ uint8_t l_module_height = 0 ;
1104
+ fapi2 ::ReturnCode l_rc = fapi2 ::FAPI2_RC_SUCCESS ;
1105
+
1106
+ FAPI_TRY (mss ::attr ::get_dram_module_height (i_target , l_module_height ));
1107
+
1108
+ // For non 4U configs, let's just VR disable down the line
1109
+ if (l_module_height == fapi2 ::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U )
1110
+ {
1111
+ // For 4U, do our defined disable sequence
1112
+ FAPI_TRY (mss ::pmic ::power_down_sequence_4u (i_target ));
1113
+ }
1114
+ else
1115
+ {
1116
+ FAPI_TRY (mss ::pmic ::power_down_sequence_1u_2u (i_target ));
1117
+ }
1118
+
1119
+ return fapi2 ::FAPI2_RC_SUCCESS ;
1120
+
1121
+ fapi_try_exit :
1122
+ return fapi2 ::current_err ;
1123
+ }
1124
+
884
1125
///
885
1126
/// @brief Disable PMICs and clear status bits in preparation for enable
886
1127
///
@@ -928,45 +1169,22 @@ fapi2::ReturnCode disable_and_reset_pmics(const fapi2::Target<fapi2::TARGET_TYPE
928
1169
}
929
1170
}
930
1171
1172
+ // Call the new PMIC power down sequence
1173
+ FAPI_TRY (pmic_power_down (i_ocmb_target ));
1174
+
931
1175
// Reverse loop
932
1176
for (int16_t l_i = (l_pmics .size () - 1 ); l_i >= 0 ; -- l_i )
933
1177
{
934
1178
const auto& PMIC = l_pmics [l_i ];
935
1179
936
- // First, disable
937
- {
938
- fapi2 ::buffer < uint8_t > l_reg_contents ;
939
-
940
- // Redundant clearBit, but just so it's clear what we're doing
941
- FAPI_TRY (mss ::pmic ::i2c ::reg_read_reverse_buffer (PMIC , REGS ::R32 , l_reg_contents ));
942
- l_reg_contents .clearBit < FIELDS ::R32_VR_ENABLE > ();
943
-
944
- // Due to long soft stop time in 4U (~8ms), let's delay for 10ms to be safe
945
- fapi2 ::delay (10 * mss ::common_timings ::DELAY_1MS , mss ::common_timings ::DELAY_1MS );
946
-
947
- // We are opting here to log RC's here as recovered. If this register write fails,
948
- // the ones later in the procedure will fail as well. The action to perform in
949
- // such a case is dependent on whether we do or do not have redundancy, which we
950
- // will know later in the procedure. As a result, we will not worry about failures here.
951
- l_rc = mss ::pmic ::i2c ::reg_write_reverse_buffer (PMIC , REGS ::R32 , l_reg_contents );
952
-
953
- if (l_rc != fapi2 ::FAPI2_RC_SUCCESS )
954
- {
955
- fapi2 ::logError (l_rc , fapi2 ::FAPI2_ERRL_SEV_RECOVERED );
956
- fapi2 ::current_err = fapi2 ::FAPI2_RC_SUCCESS ;
957
- }
958
- }
959
-
960
1180
// Now that it's disabled, let's clear the status bits so errors don't hang over into the next enable
961
- {
962
- // Similarly, we will log bad ReturnCodes here as recoverable for the reasons mentioned above
963
- l_rc = mss ::pmic ::status ::clear (PMIC );
1181
+ // Similarly, we will log bad ReturnCodes here as recoverable for the reasons mentioned above
1182
+ l_rc = mss ::pmic ::status ::clear (PMIC );
964
1183
965
- if (l_rc != fapi2 ::FAPI2_RC_SUCCESS )
966
- {
967
- fapi2 ::logError (l_rc , fapi2 ::FAPI2_ERRL_SEV_RECOVERED );
968
- fapi2 ::current_err = fapi2 ::FAPI2_RC_SUCCESS ;
969
- }
1184
+ if (l_rc != fapi2 ::FAPI2_RC_SUCCESS )
1185
+ {
1186
+ fapi2 ::logError (l_rc , fapi2 ::FAPI2_ERRL_SEV_RECOVERED );
1187
+ fapi2 ::current_err = fapi2 ::FAPI2_RC_SUCCESS ;
970
1188
}
971
1189
}
972
1190
@@ -1256,9 +1474,39 @@ fapi2::ReturnCode validate_efuse_off(const fapi2::Target<fapi2::TARGET_TYPE_PMIC
1256
1474
// Prior to turning on the efuse via the GPIO expander, we expect to see VIN below the
1257
1475
// EFUSE_OFF_HIGH threshold, as power will not be applied.
1258
1476
// Otherwise the efuse must be blown, and we should declare N-mode.
1259
- if (l_reg_contents > CONSTS ::R31_VIN_BULK_EFUSE_OFF_HIGH )
1477
+ // Will poll for 2.5 seconds for the VIN to go below 560mV. If not then will declare N-mode.
1478
+ // 25ms * 100 = 2.5 Seconds
1479
+ constexpr uint8_t POLL_2_5_SECS = 100 ;
1480
+ constexpr uint8_t THRESHOLD_HIGH = CONSTS ::R31_VIN_BULK_EFUSE_OFF_HIGH ;
1481
+ auto l_vin_below_efuse_off_high = false;
1482
+
1483
+ for (auto count = 0 ; count < POLL_2_5_SECS ; count ++ )
1484
+ {
1485
+ if (l_reg_contents > THRESHOLD_HIGH )
1486
+ {
1487
+ // Delay 25ms and read R31 for VIN value again
1488
+ fapi2 ::delay (25 * mss ::common_timings ::DELAY_1MS , mss ::common_timings ::DELAY_1MS );
1489
+ fapi2 ::current_err = mss ::pmic ::i2c ::reg_read (i_pmic_target , REGS ::R31 , l_reg_contents );
1490
+
1491
+ // Check the error on the reg_read
1492
+ if (fapi2 ::current_err != fapi2 ::FAPI2_RC_SUCCESS )
1493
+ {
1494
+ return mss ::pmic ::declare_n_mode (
1495
+ mss ::find_target < fapi2 ::TARGET_TYPE_OCMB_CHIP > (i_pmic_target ),
1496
+ mss ::index (i_pmic_target ));
1497
+ }
1498
+
1499
+ FAPI_DBG ("%s EFUSE OFF VIN_BULK Reading: 0x%02X" , mss ::c_str (i_pmic_target ), l_reg_contents );
1500
+ }
1501
+ else
1502
+ {
1503
+ l_vin_below_efuse_off_high = true;
1504
+ break ;
1505
+ }
1506
+ }
1507
+
1508
+ if (!l_vin_below_efuse_off_high )
1260
1509
{
1261
- constexpr uint8_t THRESHOLD_HIGH = CONSTS ::R31_VIN_BULK_EFUSE_OFF_HIGH ;
1262
1510
FAPI_ASSERT_NOEXIT (false,
1263
1511
fapi2 ::PMIC_EFUSE_BLOWN (fapi2 ::FAPI2_ERRL_SEV_RECOVERED )
1264
1512
.set_PMIC_TARGET (i_pmic_target )
@@ -1423,7 +1671,7 @@ fapi2::ReturnCode setup_pmic_pair_and_gpio(
1423
1671
if (!l_already_enabled )
1424
1672
{
1425
1673
// Now, sampling VIN_BULK, which is protected by a fuse, we check that VIN_BULK does not read
1426
- // more than 0.28V . If it does, then the fuse must be bad/blown, and we will declare N-mode.
1674
+ // more than 0.56V . If it does, then the fuse must be bad/blown, and we will declare N-mode.
1427
1675
1428
1676
// Validate the EFUSE readings for both PMICs
1429
1677
FAPI_TRY (run_if_present (i_pmic_map , i_pmic_id_0 , [& i_pmic_map , i_pmic_id_0 ]
0 commit comments