diff options
Diffstat (limited to 'src')
7 files changed, 633 insertions, 102 deletions
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.C index a6fe8105e..4bccb489b 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.C @@ -38,6 +38,7 @@ #include <mmio_access.H> #include <generic/memory/lib/utils/c_str.H> +#include <generic/memory/lib/utils/endian_utils.H> namespace mss { @@ -107,7 +108,7 @@ fapi2::ReturnCode putScom( const fapi2::buffer<uint64_t>& i_data) { // Converts from the scom address to the MMIO address by shifting left by 3 bits - uint64_t l_scomAddr = i_scomAddr << 3; + uint64_t l_scomAddr = i_scomAddr << OCMB_ADDR_SHIFT; return putMMIO64(i_target, l_scomAddr, i_data); } @@ -350,7 +351,7 @@ fapi2::ReturnCode getScom( fapi2::buffer<uint64_t>& o_data) { // Converts from the scom address to the MMIO address by shifting left by 3 bits - uint64_t l_scomAddr = i_scomAddr << 3; + uint64_t l_scomAddr = i_scomAddr << OCMB_ADDR_SHIFT; return getMMIO64(i_target, l_scomAddr, o_data); } diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.H index 4a0b6571e..438bb43c5 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.H @@ -128,106 +128,6 @@ static const uint64_t EXPLR_IB_SENSOR_CACHE_ADDR = EXPLR_IB_MMIO_OFFSET | 0x4008 //-------------------------------------------------------------------------------- /// -/// @brief Forces native data into LE order -/// @tparam T the data type to process -/// @param[in] i_input inputted data to process -/// @param[in,out] io_data vector to append data to -/// -template < typename T > -void forceLE(const T& i_input, std::vector<uint8_t>& io_data) -{ - // Temporary variable to process - we'll be doing bit shifts below - T l_temp = i_input; - - for(size_t i = 0; i < sizeof(i_input); i++) - { - // Grab the lowe rorder byte and add it to the back of the vector - const uint8_t l_byte = l_temp & 0xFF; - io_data.push_back(l_byte); - - // Shift higher byte value into lowest no matter existing endianness - l_temp >>= BITS_PER_BYTE; - } -} - -/// -/// @brief Forces native data into LE order for an array -/// @tparam T the data type to process -/// @param[in] i_input inputted data to process -/// @param[in] i_size size of the array -/// @param[in,out] io_data vector to append data to -/// -template < typename T > -inline void forceLEArray(const T* i_input, const uint64_t i_size, std::vector<uint8_t>& io_data) -{ - for(size_t i = 0; i < i_size; i++) - { - forceLE(i_input[i], io_data); - } -} - -/// -/// @brief Converts LE data into native order -/// @tparam T the data type to output to -/// @param[in] i_input inputted data to process -/// @param[in,out] io_idx current index -/// @param[out] o_data data that has been converted into native endianness -/// @return bool true if passing false if failing -/// @note Real FFDC will be handled outside -/// -template < typename T > -bool readLE(const std::vector<uint8_t>& i_input, uint32_t& io_idx, T& o_data) -{ - const uint32_t l_sz = static_cast<uint32_t>(sizeof(o_data)); - io_idx = l_sz + io_idx; - - // Checks that our final index is within the data range - // Note: we decrement the index prior, so equal to is ok - if(io_idx > i_input.size()) - { - return false; - } - - uint64_t l_idx = io_idx; - - o_data = 0; - - for(uint64_t i = 0; i < l_sz; i++) - { - l_idx--; - uint8_t v = i_input[l_idx]; - o_data <<= BITS_PER_BYTE; - o_data |= v; - } - - return true; -} - -/// -/// @brief Converts LE data into native order -/// @tparam T the data type to output to -/// @param[in] i_input inputted data to process -/// @param[in] i_size size of the array -/// @param[in,out] io_idx current index -/// @param[out] o_data data that has been converted into native endianness -/// @return bool true if passing false if failing -/// @note Real FFDC will be handled outside -/// -template < typename T > -bool readLEArray(const std::vector<uint8_t>& i_input, const uint32_t i_size, uint32_t& io_idx, T* o_data) -{ - // Loop while the readLE is still passing and we haven't looped through the array's boundaries - bool l_passing = true; - - for(uint32_t i = 0; i < i_size && l_passing; ++i) - { - l_passing = readLE(i_input, io_idx, o_data[i]); - } - - return l_passing; -} - -/// /// @brief Converts user_input_msdg to little endian /// @param[in] i_input user_input_msdg structure to convert /// @return vector of little endian data diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H index b153a8074..530efde2b 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H @@ -41,6 +41,8 @@ #include <vector> #include <lib/i2c/exp_i2c_fields.H> +#include <generic/memory/lib/utils/pos.H> +#include <generic/memory/lib/utils/endian_utils.H> namespace mss { @@ -178,6 +180,158 @@ inline fapi2::ReturnCode is_ready(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CH return fapi2::getI2c(i_target, l_size, l_cmd_id, l_data); } +/// +/// @brief Perform a register write operation on the given OCMB chip +/// @param[in] i_target the OCMB target +/// @param[in] i_addr The translated address on the OCMB chip +/// @param[in] i_data_buffer buffer of data we want to write to the register +/// @return FAPI2_RC_SUCCESS iff okay +/// +inline fapi2::ReturnCode fw_reg_write(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + const uint32_t i_addr, + const fapi2::buffer<uint32_t>& i_data_buffer) +{ + // create byte vector that will hold command bytes in sequence that will do the scom + std::vector<uint8_t> l_cmd_vector; + std::vector<uint8_t> l_le_addr_vector; + std::vector<uint8_t> l_le_data_vector; + uint32_t l_input_data = static_cast<uint32_t>(i_data_buffer); + + forceLE(i_addr, l_le_addr_vector); + forceLE(l_input_data, l_le_data_vector); + + // Start building the cmd vector for the write operation + l_cmd_vector.push_back(FW_REG_WRITE); // Byte 0 = 0x05 (FW_REG_WRITE) + l_cmd_vector.push_back(FW_WRITE_REG_DATA_SIZE); // Byte 1 = 0x08 (FW_SCOM_DATA_SIZE) + + // i_addr and i_data_buffer were converted to LE above so we can + // write them directly to the cmd_vector in the same order they + // currently are + // Byte 2:5 = Address + l_cmd_vector.insert(l_cmd_vector.end(), l_le_addr_vector.begin(), l_le_addr_vector.end()); + // Byte 6:9 = Data + l_cmd_vector.insert(l_cmd_vector.end(), l_le_data_vector.begin(), l_le_data_vector.end()); + + // Use fapi2 putI2c interface to execute command + FAPI_TRY(fapi2::putI2c(i_target, l_cmd_vector), + "I2C FW_REG_WRITE op failed to write to 0x%.8X on OCMB w/ fapiPos = 0x%.8X", + i_addr, mss::fapi_pos(i_target)); + + // Check status of operation + FAPI_TRY(fw_status(i_target), + "Invalid Status after FW_REG_WRITE operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X", + i_addr, mss::fapi_pos(i_target)); + + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Perform a register write operation on the given OCMB chip +/// @param[in] i_target the OCMB target +/// @param[in] i_addr The translated address on the OCMB chip +/// @param[in] o_data_buffer buffer of data we will write the contents of the register to +/// @return FAPI2_RC_SUCCESS iff okay +/// +inline fapi2::ReturnCode fw_reg_read(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + const uint32_t i_addr, + fapi2::buffer<uint32_t>& o_data_buffer) +{ + // create byte vector that will hold command bytes in sequence that will do the scom + std::vector<uint8_t> l_cmd_vector; + std::vector<uint8_t> l_read_data; + std::vector<uint8_t> l_le_addr_vector; + uint32_t l_index = 0; + uint32_t l_read_value = 0; + + forceLE(i_addr, l_le_addr_vector); + + // Build the cmd vector for the Read + l_cmd_vector.push_back(FW_REG_ADDR_LATCH); // Byte 0 = 0x03 (FW_REG_ADDR_LATCH) + l_cmd_vector.push_back(FW_REG_ADDR_LATCH_SIZE); // Byte 1 = 0x04 (FW_REG_ADDR_LATCH_SIZE) + + // i_addr was converted to LE above so we can write it + // directly to the cmd_vector in the same order it + // currently is in + // Byte 2:5 = Address + l_cmd_vector.insert(l_cmd_vector.end(), l_le_addr_vector.begin(), l_le_addr_vector.end()); + + // Use fapi2 putI2c interface to execute command + FAPI_TRY(fapi2::putI2c(i_target, l_cmd_vector), + "putI2c returned error for FW_REG_ADDR_LATCH operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X", + i_addr, mss::fapi_pos(i_target)); + + // Check i2c status after operation + FAPI_TRY(fw_status(i_target), + "Invalid Status after FW_REG_ADDR_LATCH operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X", + i_addr, mss::fapi_pos(i_target)); + + // Clear out cmd vector as i2c op is complete and we must prepare for next + l_cmd_vector.clear(); + + // Cmd vector is a single byte with FW_REG_READ code + l_cmd_vector.push_back(FW_REG_READ); // Byte 0 = 0x04 (FW_REG_READ) + + // Use fapi2 getI2c interface to execute command + FAPI_TRY(fapi2::getI2c(i_target, FW_I2C_SCOM_READ_SIZE, l_cmd_vector, l_read_data), + "getI2c returned error for FW_REG_READ operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X", + i_addr, mss::fapi_pos(i_target)); + + // The first byte returned should be the size of the remaining data + // We requested FW_REG_ADDR_LATCH_SIZE bytes so that is what we + // expect to see as the first byte. + FAPI_ASSERT( (l_read_data.front() == FW_REG_ADDR_LATCH_SIZE), + fapi2::I2C_GET_SCOM_INVALID_READ_SIZE() + .set_TARGET(i_target) + .set_ADDRESS(i_addr) + .set_SIZE_RETURNED(l_read_data[0]) + .set_SIZE_REQUESTED(FW_REG_ADDR_LATCH_SIZE), + "First byte of read data was expected to be 0x%lx but byte read = 0x%x", + FW_REG_ADDR_LATCH_SIZE, l_read_data[0] ); + + // Check i2c status after operation + FAPI_TRY(fw_status(i_target), + "Invalid Status after FW_REG_READ operation to 0x%.8X on OCMB w/ fapiPos = 0x%.8X", + i_addr, mss::fapi_pos(i_target)); + + // The OCMB is a 32-bit little endian engine so + // we must convert the buffer that we read into native + // incase native endian is different than LE + readLE(l_read_data, l_index, l_read_value); + o_data_buffer = l_read_value; + + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Perform a register write operation on the given OCMB chip +/// @param[in] i_addr The raw address that needs to be translated to IBM scom addr +/// @param[in] i_side LHS or RHS of the IBM i2c scom. IBM addresses expect 64 bits of +/// data returned from them so we must have a LHS and a RHS which is offset +/// by 4 bytes. This is because the OCMB is a 32 bit architecture +/// @return uint32 of translated address +/// +inline uint32_t trans_ibm_i2c_scom_addr(const uint32_t i_addr, + const addrSide i_side) +{ + return (i_side == LHS) ? + ((LAST_THREE_BYTES_MASK & i_addr) << OCMB_ADDR_SHIFT) | IBM_SCOM_OFFSET_LHS | OCMB_UNCACHED_OFFSET : + ((LAST_THREE_BYTES_MASK & i_addr) << OCMB_ADDR_SHIFT) | IBM_SCOM_OFFSET_RHS | OCMB_UNCACHED_OFFSET ; +} + +/// +/// @brief Perform a register write operation on the given OCMB chip +/// @param[in] i_addr The raw address that needs to be translated to Microchip scom addr +/// @return uint32 of translated address +/// +inline uint32_t trans_micro_i2c_scom_addr(const uint32_t i_addr) +{ + return (i_addr | OCMB_UNCACHED_OFFSET) ; +} + }// i2c }// exp }// mss diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c_scom.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c_scom.H new file mode 100644 index 000000000..f1d811245 --- /dev/null +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c_scom.H @@ -0,0 +1,221 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c_scom.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 exp_i2c_scom.H +/// @brief explorer I2C scom function declarations +/// +// *HWP HWP Owner: Christian Geddes <crgeddes@us.ibm.com> +// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:SBE + +#ifndef _MSS_EXP_I2C_SCOM_H_ +#define _MSS_EXP_I2C_SCOM_H_ + +#include <lib/i2c/exp_i2c.H> + + +namespace mss +{ +namespace exp +{ +namespace i2c +{ + +/// +/// @brief Perform a put scom operation over i2c to OCMB explorer chip +/// @note OCMB chip is little-endian and Host is likely running big-endian +/// +/// @param[in] i_addr 32 bit IBM scom address we want to write on the OCMB +/// @param[in] i_target the OCMB target +/// @param[in] i_data_buffer Contains data which will be written to i_addr on i_target +/// +/// @return FAPI2_RC_SUCCESS iff okay +/// +/// @note this is the IBM scom version the overloaded function i2c_put_scom +/// IBM i2c scoms to the explorer chips are 64 bits of data +fapi2::ReturnCode i2c_put_scom( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + const uint32_t i_addr, + const fapi2::buffer<uint64_t>& i_data_buffer) +{ + // We need to separate 64 bit input buffer into two 32-bit halves, + // use this 32-bit buffer to pull out 32 bits at a time + fapi2::buffer<uint32_t> l_side_specific_buffer; + + // check if this is an IBM address + FAPI_ASSERT( ((i_addr & FIRST_BYTE_MASK) == IBM_SCOM_INDICATOR), + fapi2::I2C_SCOM_EXPECTED_IBM_INDICATOR() + .set_TARGET(i_target) + .set_ADDRESS(i_addr), + "First byte of 0x%lx does not = 0x%lx, address is not valid for IBM I2C scom", + i_addr, IBM_SCOM_INDICATOR); + + // The LHS is the bits 0-31 of the input buffer + i_data_buffer.extractToRight<0, 32>(l_side_specific_buffer); + + // Perform the write operation to complete the LHS of the write + FAPI_TRY(fw_reg_write(i_target, trans_ibm_i2c_scom_addr(i_addr, LHS), l_side_specific_buffer), + "(LHS) Failed i2c scom register write to ibm scom addr 0x%lx on OCMB w/ fapi_pos = %d", + i_addr, mss::fapi_pos(i_target)); + + // The RHS is the bits 32-63 of the input buffer + i_data_buffer.extractToRight<32, 32>(l_side_specific_buffer); + + // Perform the write operation to complete the RHS of the write + FAPI_TRY(fw_reg_write(i_target, trans_ibm_i2c_scom_addr(i_addr, RHS), l_side_specific_buffer), + "(RHS) Failed i2c scom register write to ibm scom addr 0x%lx on OCMB w/ fapi_pos = %d", + i_addr, mss::fapi_pos(i_target) ); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Perform a put scom operation over i2c to OCMB explorer chip +/// @note OCMB chip is little-endian and Host is likely running big-endian +/// @param[in] i_target the OCMB target +/// @param[in] i_addr 32 bit Microchip scom address we want to write on the OCMB +/// @param[in] i_data_buffer Contains data which will be written to i_addr on i_target +/// +/// @return FAPI2_RC_SUCCESS iff okay +/// +/// @note this is the Microchip scom version the overloaded function i2c_put_scom +/// Microchip i2c scoms to the explorer chips are 32 bits of data +fapi2::ReturnCode i2c_put_scom( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + const uint32_t i_addr, + const fapi2::buffer<uint32_t>& i_data_buffer) +{ + // The micro-semi addresses should not have the IBM indicator + FAPI_ASSERT( ((i_addr & FIRST_BYTE_MASK) != IBM_SCOM_INDICATOR), + fapi2::I2C_SCOM_UNEXPECTED_IBM_INDICATOR() + .set_TARGET(i_target) + .set_ADDRESS(i_addr), + "First byte of 0x%lx == 0x%lx, address is not valid for microchip I2C scom", + i_addr, IBM_SCOM_INDICATOR); + + // Perform the write operation, note we must apply the UNCACHED_OFFSET to the + // address before performing the write + // Also note that we pass i_data_buffer directly to the fw_reg_read function + FAPI_TRY(fw_reg_write(i_target, trans_micro_i2c_scom_addr(i_addr) , i_data_buffer), + "Failed i2c scom register write to microchip scom addr 0x%lx on OCMB w/ fapi_pos = %d", + i_addr, mss::fapi_pos(i_target)); + +fapi_try_exit: + return fapi2::current_err; + +} + + + + +/// +/// @brief Perform a get scom operation over i2c to OCMB explorer chip +/// @note OCMB chip is little-endian and Host is likely running big-endian +/// @param[in] i_target the OCMB target +/// @param[in] i_addr 32 bit IBM scom address we want to read from on the OCMB +/// @param[out] o_data_buffer Buffer where data found at i_addr will be written to +/// +/// @return FAPI2_RC_SUCCESS iff okay +/// +/// @note this is the IBM scom version the overloaded function i2c_get_scom +/// IBM i2c scoms to the explorer chips are 64 bits of data +fapi2:: ReturnCode i2c_get_scom(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + const uint32_t i_addr, + fapi2::buffer<uint64_t>& o_data_buffer) +{ + // IBM get scom expects 64 bits of data returned but we can only + // read 32 bits of data per command so we will do 2 reads in this getscom step. + fapi2::buffer<uint32_t> l_read_buffer; + + // check if this is an IBM address + FAPI_ASSERT( ((i_addr & FIRST_BYTE_MASK) == IBM_SCOM_INDICATOR), + fapi2::I2C_SCOM_EXPECTED_IBM_INDICATOR() + .set_TARGET(i_target) + .set_ADDRESS(i_addr), + "First byte of 0x%lx does not = 0x%lx, address is not valid for IBM I2C scom", + i_addr, IBM_SCOM_INDICATOR); + + FAPI_TRY(fw_reg_read(i_target, trans_ibm_i2c_scom_addr(i_addr, LHS), l_read_buffer), + "(LHS) Failed i2c scom register read from ibm scom addr 0x%.8X on OCMB w/ fapiPos = 0x%.8X", + i_addr, mss::fapi_pos(i_target)); + + // Data was put in correct order by fw_reg_read, copy data to LHS of out buffer + o_data_buffer.insertFromRight<0, 32>(l_read_buffer); + + FAPI_TRY(fw_reg_read(i_target, trans_ibm_i2c_scom_addr(i_addr, RHS), l_read_buffer), + "(RHS) Failed i2c scom register read from ibm scom addr 0x%.8X on OCMB w/ fapiPos = 0x%.8X", + i_addr, mss::fapi_pos(i_target)); + + // Data was put in correct order by fw_reg_read, copy data to RHS of out buffer + o_data_buffer.insertFromRight<32, 32>(l_read_buffer); + + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Perform a get scom operation over i2c to OCMB explorer chip +/// @note OCMB chip is little-endian and Host is likely running big-endian +/// @param[in] i_target the OCMB target +/// @param[in] i_addr 32 bit Microchip scom address we want to read from on the OCMB +/// @param[out] o_data_buffer Buffer where data found at i_addr will be written to +/// +/// @return FAPI2_RC_SUCCESS iff okay +/// +/// @note this is the Microchip scom version the overloaded function i2c_get_scom +/// Microchip i2c scoms to the explorer chips are 32 bits of data +fapi2:: ReturnCode i2c_get_scom(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + const uint32_t i_addr, + fapi2::buffer<uint32_t>& o_data_buffer) +{ + // The micro-semi addresses should not have the IBM indicator + FAPI_ASSERT( ((i_addr & FIRST_BYTE_MASK) != IBM_SCOM_INDICATOR), + fapi2::I2C_SCOM_UNEXPECTED_IBM_INDICATOR() + .set_TARGET(i_target) + .set_ADDRESS(i_addr), + "First byte of 0x%lx == 0x%lx, address is not valid for microchip I2C scom", + i_addr, IBM_SCOM_INDICATOR); + + // Perform the read operation, note we must apply the UNCACHED_OFFSET to the + // address before performing the read. + // Also note that we pass o_data_buffer directly to the fw_reg_read function + FAPI_TRY(fw_reg_read(i_target, trans_micro_i2c_scom_addr(i_addr) , o_data_buffer), + "Failed i2c scom register read from microchip scom addr 0x%.8X on OCMB w/ fapiPos = 0x%.8X", + i_addr, mss::fapi_pos(i_target)); + + +fapi_try_exit: + return fapi2::current_err; +} + +} // end i2c namespace +} // end exp namespace +} // end mss namespace + +#endif diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H index 53bedae7c..223b97ca7 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H @@ -41,6 +41,8 @@ namespace mss namespace exp { +constexpr uint32_t OCMB_ADDR_SHIFT = 3; + /// /// @brief explorer ffdc codes /// @@ -78,6 +80,10 @@ enum sizes FW_BOOT_CONFIG_BYTE_LEN = 4, FW_STATUS_BYTE_LEN = 4, + FW_WRITE_REG_DATA_SIZE = 0x08, + FW_REG_ADDR_LATCH_SIZE = 0x04, + FW_I2C_SCOM_READ_SIZE = 0x05, + // Largest R/W length for bytes of data MIN_DATA_BYTES_LEN = 1, MAX_DATA_BYTES_LEN = 32, @@ -122,6 +128,44 @@ enum boot_stages FW_UPGRADE_MODE = 0x02, RUNTIME_FW = 0x03, }; + +/// +/// @brief Useful constants for i2c scom functionality +/// +/// @note FIRST_BYTE_MASK = allows us to mask off first by of +/// an address to check if its an IBM SCOM +/// LAST_THREE_BYTES_MASK = used as part of formula to translate +/// a given address to an IBM scom address +/// OCBM_UNCACHED_OFFSET = Also used as part of formula for translating +/// a given address to the correct IBM or microchip form +/// IBM_SCOM_OFFSET_LHS and IBM_SCOM_OFFSET_RHS are used in formula +/// for calculating IBM scom address for left and right side of addr +/// IBM_SCOM_INDICATOR is the indicator bit in the first byte of an +/// address that tells us if it is a IBM scom or not +/// +enum i2c_scom_consts : uint32_t +{ + FIRST_BYTE_MASK = 0xFF000000, + LAST_THREE_BYTES_MASK = 0x00FFFFFF, + OCMB_UNCACHED_OFFSET = 0xA0000000, + IBM_SCOM_OFFSET_LHS = 0x08000000, + IBM_SCOM_OFFSET_RHS = 0x08000004, + IBM_SCOM_INDICATOR = IBM_SCOM_OFFSET_LHS, +}; + +/// +/// @brief Simple enum allows code to pick between left and right +/// +/// This is used when deciding if we are writing/reading from left +/// side of IBM address or right side. This is needed because IBM +/// scoms are 64 bits while the OCMB only has 32 bit regs. +enum addrSide +{ + LHS = 0x00, + RHS = 0x01 +}; + + }// i2c }// exp }// mss diff --git a/src/import/chips/ocmb/explorer/procedures/xml/error_info/exp_i2c_scom_errors.xml b/src/import/chips/ocmb/explorer/procedures/xml/error_info/exp_i2c_scom_errors.xml new file mode 100644 index 000000000..bfe2e65ef --- /dev/null +++ b/src/import/chips/ocmb/explorer/procedures/xml/error_info/exp_i2c_scom_errors.xml @@ -0,0 +1,62 @@ +<!-- IBM_PROLOG_BEGIN_TAG --> +<!-- This is an automatically generated prolog. --> +<!-- --> +<!-- $Source: src/import/chips/ocmb/explorer/procedures/xml/error_info/exp_i2c_scom_errors.xml $ --> +<!-- --> +<!-- 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 --> +<hwpErrors> + <hwpError> + <rc>RC_I2C_GET_SCOM_INVALID_READ_SIZE</rc> + <description> + First Byte data returned from the i2c register read contains + the size of the remaining bytes returned. This should match + the number of bytes we requested. + </description> + <ffdc>TARGET</ffdc> + <ffdc>ADDRESS</ffdc> + <ffdc>SIZE_RETURNED</ffdc> + <ffdc>SIZE_REQUESTED</ffdc> + </hwpError> + + <hwpError> + <rc>RC_I2C_SCOM_EXPECTED_IBM_INDICATOR</rc> + <description> + First Byte of the address passed to i2c_scom operation did not match + what was required for IBM scom. I2c scoms associated with 64 bits of + are assumed to be IBM scoms and must have 0x08 set in the first byte + of the address. + </description> + <ffdc>TARGET</ffdc> + <ffdc>ADDRESS</ffdc> + </hwpError> + + <hwpError> + <rc>RC_I2C_SCOM_UNEXPECTED_IBM_INDICATOR</rc> + <description> + First Byte of the address passed to i2c_scom operation had 0x08 set which + indicates IBM scom. But the data associated with the address does not + match IBM scom data size. + </description> + <ffdc>TARGET</ffdc> + <ffdc>ADDRESS</ffdc> + </hwpError> + + </hwpErrors> diff --git a/src/import/generic/memory/lib/utils/endian_utils.H b/src/import/generic/memory/lib/utils/endian_utils.H new file mode 100644 index 000000000..5d59be68b --- /dev/null +++ b/src/import/generic/memory/lib/utils/endian_utils.H @@ -0,0 +1,149 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/generic/memory/lib/utils/endian_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 endian_utils.H +/// @brief Util functions to help with endianess +/// + +// *HWP HWP Owner: Ben Gass <bgass@us.ibm.com> +// *HWP HWP Backup: Christian Geddes <crgeddes@us.ibm.com> +// *HWP Team: +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +#ifndef _ENDIAN_UTILS_H_ +#define _ENDIAN_UTILS_H_ + +#include <cstdint> +#include <vector> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> + +namespace mss +{ + +/// +/// @brief Forces native data into LE order +/// @tparam T the data type to process +/// @param[in] i_input inputted data to process +/// @param[in,out] io_data vector to append data to +/// +template < typename T > +void forceLE(const T& i_input, std::vector<uint8_t>& io_data) +{ + // Temporary variable to process - we'll be doing bit shifts below + T l_temp = i_input; + + for(size_t i = 0; i < sizeof(i_input); i++) + { + // Grab the lowe rorder byte and add it to the back of the vector + const uint8_t l_byte = l_temp & 0xFF; + io_data.push_back(l_byte); + + // Shift higher byte value into lowest no matter existing endianness + l_temp >>= BITS_PER_BYTE; + } +} + +/// +/// @brief Forces native data into LE order for an array +/// @tparam T the data type to process +/// @param[in] i_input inputted data to process +/// @param[in] i_size size of the array +/// @param[in,out] io_data vector to append data to +/// +template < typename T > +inline void forceLEArray(const T* i_input, const uint64_t i_size, std::vector<uint8_t>& io_data) +{ + for(size_t i = 0; i < i_size; i++) + { + forceLE(i_input[i], io_data); + } +} + +/// +/// @brief Converts LE data into native order +/// @tparam T the data type to output to +/// @param[in] i_input inputted data to process +/// @param[in,out] io_idx current index +/// @param[out] o_data data that has been converted into native endianness +/// @return bool true if passing false if failing +/// @note Real FFDC will be handled outside +/// +template < typename T > +bool readLE(const std::vector<uint8_t>& i_input, uint32_t& io_idx, T& o_data) +{ + const uint32_t l_sz = static_cast<uint32_t>(sizeof(o_data)); + io_idx = l_sz + io_idx; + + // Checks that our final index is within the data range + // Note: we decrement the index prior, so equal to is ok + if(io_idx > i_input.size()) + { + return false; + } + + uint64_t l_idx = io_idx; + + o_data = 0; + + for(uint64_t i = 0; i < l_sz; i++) + { + l_idx--; + uint8_t v = i_input[l_idx]; + o_data <<= BITS_PER_BYTE; + o_data |= v; + } + + return true; +} + +/// +/// @brief Converts LE data into native order +/// @tparam T the data type to output to +/// @param[in] i_input inputted data to process +/// @param[in] i_size size of the array +/// @param[in,out] io_idx current index +/// @param[out] o_data data that has been converted into native endianness +/// @return bool true if passing false if failing +/// @note Real FFDC will be handled outside +/// +template < typename T > +bool readLEArray(const std::vector<uint8_t>& i_input, const uint32_t i_size, uint32_t& io_idx, T* o_data) +{ + // Loop while the readLE is still passing and we haven't looped through the array's boundaries + bool l_passing = true; + + for(uint32_t i = 0; i < i_size && l_passing; ++i) + { + l_passing = readLE(i_input, io_idx, o_data[i]); + } + + return l_passing; +} + +} + +#endif |