summaryrefslogtreecommitdiffstats
path: root/src/import/chips/ocmb/explorer/procedures/hwp
diff options
context:
space:
mode:
authorChristian Geddes <crgeddes@us.ibm.com>2018-10-24 10:47:24 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-11-05 22:11:45 -0600
commit0e15017d11ea9ff2dd705119feeb9ed73ed405dc (patch)
treecae5e4b317f5e7bdb9dd28ee272d809491622d1c /src/import/chips/ocmb/explorer/procedures/hwp
parentc826f6afcb57031ebf3a8fa948926feaf5792497 (diff)
downloadtalos-hostboot-0e15017d11ea9ff2dd705119feeb9ed73ed405dc.tar.gz
talos-hostboot-0e15017d11ea9ff2dd705119feeb9ed73ed405dc.zip
Add exp_i2c_scom driver that will be consumed by HB/SBE platforms
This commit adds a new exp_i2c_scom.H file which contains two functions, i2c_get_scom and i2c_put_scom. These functions will take in a fapi2 OCMB target, an address and a buffer that either contains scom data to write or space for scom data to be written to. The functions use the fapi2::puti2c / fapi2::geti2c interfaces to perform the scoms. Change-Id: I4de680e187258cbfc57dd71f698dc1fc8760cefb RTC:196806 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/67949 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/67961 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips/ocmb/explorer/procedures/hwp')
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.C5
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_inband.H100
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c.H154
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/i2c/exp_i2c_scom.H221
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H44
5 files changed, 422 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
OpenPOWER on IntegriCloud