/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/import/generic/memory/lib/spd/spd_utils.H $ */ /* */ /* OpenPOWER HostBoot Project */ /* */ /* Contributors Listed Below - COPYRIGHT 2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ /* You may obtain a copy of the License at */ /* */ /* http://www.apache.org/licenses/LICENSE-2.0 */ /* */ /* Unless required by applicable law or agreed to in writing, software */ /* distributed under the License is distributed on an "AS IS" BASIS, */ /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ /* implied. See the License for the specific language governing */ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ /// /// @file spd_utls.H /// @brief SPD utility functions definitions /// // *HWP HWP Owner: Andre Marin // *HWP HWP Backup: Stephen Glancy // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: HB:FSP #ifndef _MSS_SPD_UTILS_H_ #define _MSS_SPD_UTILS_H_ #include #include #include namespace mss { namespace spd { /// /// @brief Calculates timing value /// @param[in] i_timing_mtb timing value in MTB units /// @param[in] i_mtb_multiplier SPD medium timebase /// @param[in] i_timing_ftb fine offset of timing value /// @param[in] i_ftb_multiplier SPD fine timebase /// @return the timing value in picoseconds /// inline int64_t calc_timing_from_timebase(const int64_t i_timing_mtb, const int64_t i_mtb_multiplier, const int64_t i_timing_ftb, const int64_t i_ftb_multiplier) { // JEDEC algorithm const int64_t l_timing_val = i_timing_mtb * i_mtb_multiplier; const int64_t l_fine_offset = i_timing_ftb * i_ftb_multiplier; return l_timing_val + l_fine_offset; } /// /// @brief Helper to compute JEDEC's SPD rounding algorithm /// to convert ps to nCK /// @tparam T input type /// @tparam OT output type /// @param[in] i_timing_in_ps timing parameter in ps /// @param[in] i_tck_in_ps clock period in ps /// @param[in] i_inverse_corr_factor inverse correction factor (defined by JEDEC) /// @param[out] o_value_nck the end calculation in nck /// @return true if overflow didn't occur, false otherwise /// @note DDR4 SPD Contents Rounding Algorithm /// @note Item 2220.46 /// template static inline bool jedec_spd_rounding_alg(const T& i_timing_in_ps, const T& i_tck_in_ps, const guard_band i_inverse_corr_factor, OT& o_val_nck) { // Preliminary nCK calculation, scaled by 1000 per JDEC algorithm T l_temp_nck = (i_timing_in_ps * mss::CONVERT_PS_IN_A_NS) / (i_tck_in_ps == 0 ? 1 : i_tck_in_ps); l_temp_nck += i_inverse_corr_factor; l_temp_nck = l_temp_nck / mss::CONVERT_PS_IN_A_NS; // Check for overflow // static_cast needed for HB compiler that complains about // comparision of two different integral types o_val_nck = l_temp_nck; FAPI_DBG("Input timing (ps) %d, tCK (ps) %d, temp output %d, output (nCK) %d", i_timing_in_ps, i_tck_in_ps, l_temp_nck, o_val_nck); return (static_cast(o_val_nck) == l_temp_nck); } /// /// @brief Returns clock cycles based on input application period /// @tparam T input type /// @tparam OT output type /// @param[in] i_timing_in_ps timing parameter in ps /// @param[in] i_tck_in_ps clock period in ps /// @param[in] i_inverse_corr_factor inverse correction factor (defined by JEDEC) /// @param[out] o_value_nck the end calculation in nck /// @return FAPI2_RC_SUCCESS iff okay /// @note DDR4 SPD Contents Rounding Algorithm /// @note Item 2220.46 /// template inline fapi2::ReturnCode calc_nck(const T& i_timing_in_ps, const T& i_tck_in_ps, const guard_band i_inverse_corr_factor, OT& o_val_nck) { FAPI_ASSERT( jedec_spd_rounding_alg(i_timing_in_ps, i_tck_in_ps, i_inverse_corr_factor, o_val_nck), fapi2::MSS_INVALID_CAST_CALC_NCK(). set_TIMING_PS(i_timing_in_ps). set_NCK_NS(i_tck_in_ps). set_CORRECTION_FACTOR(i_inverse_corr_factor), "Overflow occured. Returned data is %d", o_val_nck); // If we don't assert, we don't know what's in current_err ... return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: return fapi2::current_err; } /// /// @brief Helper function to retrieves medium and fine timebase values /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_mtb the medium timebase (MTB) from SPD /// @param[out] o_ftb the fine timebase (FTB) from SPD /// @return FAPI2_RC_SUCCESS iff ok /// fapi2::ReturnCode get_timebases( const mss::spd::facade& i_spd_decoder, int64_t& o_mtb, int64_t& o_ftb ); /// /// @brief Retrieves SDRAM Minimum Cycle Time (tCKmin) from SPD /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_value tCKmin value in ps /// @return FAPI2_RC_SUCCESS iff ok /// fapi2::ReturnCode get_tckmin( const mss::spd::facade& i_spd_decoder, uint64_t& o_value ); /// /// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD /// @param[in] i_spd_decoder SPD decoder /// @param[out] o_value tCKmax value in ps /// @return FAPI2_RC_SUCCESS iff ok /// fapi2::ReturnCode get_tckmax( const mss::spd::facade& i_spd_decoder, uint64_t& o_value ); }// spd }// mss #endif // _MSS_SPD_UTILS_H_