summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H3
-rw-r--r--src/usr/expaccess/test/exptest_utils.C30
-rw-r--r--src/usr/expaccess/test/exptest_utils.H6
-rw-r--r--src/usr/expaccess/test/ocmbcommtest.H146
-rw-r--r--src/usr/fapi2/plat_mmio_access.C310
-rw-r--r--src/usr/targeting/common/xmltohb/attribute_types.xml15
-rw-r--r--src/usr/targeting/common/xmltohb/target_types.xml3
7 files changed, 481 insertions, 32 deletions
diff --git a/src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H b/src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H
index 2cc133468..793474322 100644
--- a/src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H
+++ b/src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H
@@ -73,6 +73,8 @@ namespace fapi2
MOD_FAPI2_PLAT_GET_FREQ_MCA_MHZ = 0x1E,
MOD_GET_OMI_FREQ_AND_VCO = 0x1F,
MOD_FAPI2_SPD_ACCESS = 0x20,
+ MOD_FAPI2_EXPLR_IB_I2C_READ = 0x21,
+ MOD_FAPI2_EXPLR_IB_I2C_WRITE = 0x22,
};
/**
@@ -134,6 +136,7 @@ namespace fapi2
RC_FAILED_TO_GET_RING_LIST = FAPI2_COMP_ID | 0x40,
RC_ATTR_OVERRIDE_DISALLOWED = FAPI2_COMP_ID | 0x41,
RC_UNKNOWN_OCMB_CHIP_TYPE = FAPI2_COMP_ID | 0x42,
+ RC_INVALID_BUFFER_SIZE = FAPI2_COMP_ID | 0x43,
// HWP generated errors
RC_HWP_GENERATED_ERROR = HWPF_COMP_ID | 0x0f,
diff --git a/src/usr/expaccess/test/exptest_utils.C b/src/usr/expaccess/test/exptest_utils.C
index 46421fc4a..01096716f 100644
--- a/src/usr/expaccess/test/exptest_utils.C
+++ b/src/usr/expaccess/test/exptest_utils.C
@@ -103,4 +103,34 @@ namespace exptest
mutex_unlock(l_mutex);
};
+ void disableInbandScomsOcmb(const TARGETING::TargetHandle_t i_ocmbTarget)
+ {
+ mutex_t* l_mutex = nullptr;
+
+ assert((i_ocmbTarget != nullptr),
+ "disableInbandScomsOcmb: target is NULL!");
+
+ // Verify that the target is of type OCMB_CHIP
+ TARGETING::ATTR_TYPE_type l_targetType =
+ i_ocmbTarget->getAttr<TARGETING::ATTR_TYPE>();
+ assert((l_targetType == TARGETING::TYPE_OCMB_CHIP),
+ "disableInbandScomsOcmb: target is not an OCMB chip!");
+
+ TS_INFO("disableInbandScomsOcmb: switching to use i2c on OCMB 0x%08x",
+ TARGETING::get_huid(i_ocmbTarget));
+
+ //don't mess with attributes without the mutex (just to be safe)
+ l_mutex = i_ocmbTarget->getHbMutexAttr<TARGETING::ATTR_IBSCOM_MUTEX>();
+ mutex_lock(l_mutex);
+
+ TARGETING::ScomSwitches l_switches =
+ i_ocmbTarget->getAttr<TARGETING::ATTR_SCOM_SWITCHES>();
+ l_switches.useInbandScom = 0;
+ l_switches.useI2cScom = 1;
+
+ // Modify attribute
+ i_ocmbTarget->setAttr<TARGETING::ATTR_SCOM_SWITCHES>(l_switches);
+ mutex_unlock(l_mutex);
+ };
+
}
diff --git a/src/usr/expaccess/test/exptest_utils.H b/src/usr/expaccess/test/exptest_utils.H
index a62b4de71..babba0fcf 100644
--- a/src/usr/expaccess/test/exptest_utils.H
+++ b/src/usr/expaccess/test/exptest_utils.H
@@ -53,6 +53,12 @@ TARGETING::HB_MUTEX_SERIALIZE_TEST_LOCK_ATTR getTestMutex(void);
* @param[in] i_ocmbTarget The target OCMB chip
*/
void enableInbandScomsOcmb(const TARGETING::TargetHandle_t i_ocmbTarget);
+
+/**
+ * @brief Disable inband scoms on an OCMB target (use i2c instead)
+ * @param[in] i_ocmbTarget The target OCMB chip
+ */
+void disableInbandScomsOcmb(const TARGETING::TargetHandle_t i_ocmbTarget);
}
#endif
diff --git a/src/usr/expaccess/test/ocmbcommtest.H b/src/usr/expaccess/test/ocmbcommtest.H
index b804ecb1b..3c5486a1b 100644
--- a/src/usr/expaccess/test/ocmbcommtest.H
+++ b/src/usr/expaccess/test/ocmbcommtest.H
@@ -131,11 +131,13 @@ class OCMBCommTest: public CxxTest::TestSuite
}
/**
- * @brief Test the Explorer inband command/response path
+ * @brief Send and check get_properties Explorer inband command
+ * @return Number of failures
*/
- void testOcmbInbandCmdRsp( void )
+ int sendOcmbInbandCmdRsp(bool setScomI2c)
{
errlHndl_t l_errl = nullptr;
+ uint8_t failures = 0;
// Create a vector of TARGETING::Target pointers
TARGETING::TargetHandleList l_chipList;
@@ -150,19 +152,22 @@ class OCMBCommTest: public CxxTest::TestSuite
// Create a non-destructive get_properties command
buildPropertiesGetCmd(l_cmd);
- if (!iv_serializeTestMutex)
- {
- TS_FAIL("iv_serializedTestMutex is not setup, unable to continue");
- }
- else
+ for (auto & l_ocmb: l_chipList)
{
- // Inband operations can't be run at the same time
- // atomic section >>
- mutex_lock(iv_serializeTestMutex);
-
- for (auto & l_ocmb: l_chipList)
+ do
{
- FAPI_INF("testOcmbInbandCmdRsp: testing 0x%.8X OCMB", TARGETING::get_huid(l_ocmb));
+ if (setScomI2c)
+ {
+ FAPI_INF("sendOcmbInbandCmdRsp: testing 0x%.8X OCMB using I2C", TARGETING::get_huid(l_ocmb));
+ // disable inband and use i2c when possible
+ exptest::disableInbandScomsOcmb(l_ocmb);
+ }
+ else
+ {
+ FAPI_INF("sendOcmbInbandCmdRsp: testing 0x%.8X OCMB using MMIO", TARGETING::get_huid(l_ocmb));
+ // just incase some other test disabled inband scoms
+ exptest::enableInbandScomsOcmb(l_ocmb);
+ }
fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>l_fapi2_target( l_ocmb );
@@ -175,10 +180,11 @@ class OCMBCommTest: public CxxTest::TestSuite
{
TS_FAIL("Error from putCMD for 0x%.8X target",
TARGETING::get_huid(l_ocmb));
+ failures++;
break;
}
- FAPI_INF("testOcmbInbandCmdRsp: reading response");
+ FAPI_INF("sendOcmbInbandCmdRsp: reading response");
// grab the response
FAPI_INVOKE_HWP(l_errl, mss::exp::ib::getRSP, l_fapi2_target,
@@ -188,6 +194,7 @@ class OCMBCommTest: public CxxTest::TestSuite
TS_FAIL("Error from getRSP for 0x%.8X target, plid=0x%X rc=0x%X",
TARGETING::get_huid(l_ocmb),
ERRL_GETPLID_SAFE(l_errl), ERRL_GETRC_SAFE(l_errl));
+ failures++;
break;
}
@@ -199,6 +206,7 @@ class OCMBCommTest: public CxxTest::TestSuite
{
TS_FAIL("Unexpected response length 0x%.8X (expected 0x%.8X)",
l_rsp.response_length, sizeof(FW_ADAPTER_PROPERTIES_type));
+ failures++;
break;
}
@@ -213,21 +221,121 @@ class OCMBCommTest: public CxxTest::TestSuite
{
TS_FAIL("Expected chip_version to start with 0x88, found 0x%02X",
l_fw_adapter_data.chip_version[0]);
+ failures++;
}
- }
-
- // << atomic section
- mutex_unlock(iv_serializeTestMutex);
+ } while (0);
if (l_errl)
{
+ // Commit the error as this is NOT expected and
+ // needs to be investigated
errlCommit( l_errl, TARG_COMP_ID );
}
+
+ if (setScomI2c)
+ {
+ // Default the ocmb back to inband communication
+ exptest::enableInbandScomsOcmb(l_ocmb);
+ }
}
- FAPI_INF("testOcmbInbandCmdRsp: exiting");
+
+ FAPI_INF("sendOcmbInbandCmdRsp: exiting");
+ return failures;
};
/**
+ * @brief Test the Explorer inband command/response path over MMIO
+ */
+ void testOcmbInbandCmdRspOverMMIO( void )
+ {
+ if (!iv_serializeTestMutex)
+ {
+ TS_FAIL("iv_serializedTestMutex is not setup, unable to continue");
+ }
+ else
+ {
+ // Inband operations can't be run at the same time
+ // atomic section >>
+ mutex_lock(iv_serializeTestMutex);
+
+ int failures = sendOcmbInbandCmdRsp(false);
+ if (failures)
+ {
+ TS_FAIL("testOcmbInbandCmdRspOverMMIO() failed: %d", failures);
+ }
+ mutex_unlock(iv_serializeTestMutex);
+ }
+ }
+
+ /**
+ * @brief Test the Explorer inband command/response path over I2C
+ * using ATTR_FORCE_SRAM_MMIO_OVER_I2C
+ */
+ void testOcmbInbandCmdRspOverI2c_via_force( void )
+ {
+ FAPI_INF("testOcmbInbandCmdRspOverI2c_via_force: entering");
+ if (!iv_serializeTestMutex)
+ {
+ TS_FAIL("iv_serializedTestMutex is not setup, unable to continue");
+ }
+ else
+ {
+ // Inband operations can't be run at the same time
+ // atomic section >>
+ mutex_lock(iv_serializeTestMutex);
+
+ // Set FORCE_SRAM_MMIO_OVER_I2C to change to use I2C instead of MMIO
+ TARGETING::Target * l_sys = nullptr;
+ TARGETING::targetService().getTopLevelTarget(l_sys);
+ crit_assert(l_sys != nullptr);
+
+ l_sys->setAttr<TARGETING::ATTR_FORCE_SRAM_MMIO_OVER_I2C>(0x01);
+
+ int failures = sendOcmbInbandCmdRsp(false);
+ if (failures)
+ {
+ TS_FAIL("testOcmbInbandCmdRspOverI2c_via_force() failed: %d", failures);
+ }
+
+ // Restore using MMIO instead of I2C
+ l_sys->setAttr<TARGETING::ATTR_FORCE_SRAM_MMIO_OVER_I2C>(0x00);
+
+ mutex_unlock(iv_serializeTestMutex);
+ }
+ FAPI_INF("testOcmbInbandCmdRspOverI2c_via_force: exiting");
+ }
+
+ /**
+ * @brief Test the Explorer inband command/response path over I2C
+ * using scom setting to i2c
+ */
+ void testOcmbInbandCmdRspOverI2c_via_scom_switch( void )
+ {
+ FAPI_INF("testOcmbInbandCmdRspOverI2c_via_scom_switch: entering");
+ if (!iv_serializeTestMutex)
+ {
+ TS_FAIL("iv_serializedTestMutex is not setup, unable to continue");
+ }
+ else
+ {
+ // Inband operations can't be run at the same time
+ // atomic section >>
+ mutex_lock(iv_serializeTestMutex);
+
+ // Set SCOM_SWITCHES to use i2c instead of MMMIO when
+ // running the inband cmd/rsp operations
+ int failures = sendOcmbInbandCmdRsp(true);
+ if (failures)
+ {
+ TS_FAIL("testOcmbInbandCmdRspOverI2c_via_scom_switch() failed: %d", failures);
+ }
+
+ mutex_unlock(iv_serializeTestMutex);
+ }
+ FAPI_INF("testOcmbInbandCmdRspOverI2c_via_scom_switch: exiting");
+ }
+
+ /**
* @brief Constructor
*/
OCMBCommTest() : CxxTest::TestSuite()
diff --git a/src/usr/fapi2/plat_mmio_access.C b/src/usr/fapi2/plat_mmio_access.C
index 60526761b..365aa1f22 100644
--- a/src/usr/fapi2/plat_mmio_access.C
+++ b/src/usr/fapi2/plat_mmio_access.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -39,9 +39,272 @@
#include <hwpf_fapi2_reasoncodes.H>
#include <fapi2/plat_mmio_access.H>
-
namespace fapi2
{
+// Address bit that designates it as an Explorer MMIO address
+static const uint64_t EXPLR_IB_MMIO_OFFSET = 0x0000000100000000ull;
+
+// Valid I2C access to 256MB SRAM space, starts at offset 0x01000000
+static const uint64_t MIN_I2C_SRAM_SPACE_ADDRESS = 0x0000000001000000ull;
+static const uint64_t MAX_I2C_SRAM_SPACE_ADDRESS = 0x0000000001030000ull;
+
+// byte transaction sizes for i2c
+static const size_t I2C_TRANSACTION_SIZE = 4; // actual size sent
+static const size_t SCOM_I2C_TRANSACTION_SIZE = 8;
+
+// Convert MMIO to I2C address (need these bits set)
+static const uint64_t EXPLR_MMIO_TO_I2C_ADDRESS_MASK = 0xA0000000;
+
+
+/**
+ * @brief Explorer Inband read via i2c
+ * @param[in] i_target - OCMB target
+ * @param[in/out] io_data_read - buffer to be filled with read data
+ * @param[in/out] io_get_size - size of buffer (returns read size)
+ * @param[in] i_i2c_addr - i2c scom address
+ * @return errlHndl_t indicating success or failure
+ */
+errlHndl_t explrIbI2cRead(TARGETING::Target * i_target,
+ uint8_t * io_data_read,
+ size_t io_get_size,
+ const uint64_t i_i2c_addr)
+{
+ errlHndl_t l_err = nullptr;
+
+ if ( io_get_size % I2C_TRANSACTION_SIZE )
+ {
+ // invalid size expected (needs to be a multiple of I2C_TRANSACTION_SIZE)
+ FAPI_ERR("explrIbI2cRead: read size %d is not a multiple of %d",
+ io_get_size, I2C_TRANSACTION_SIZE);
+ /*@
+ * @errortype
+ * @moduleid fapi2::MOD_FAPI2_EXPLR_IB_I2C_READ
+ * @reasoncode fapi2::RC_INVALID_BUFFER_SIZE
+ * @userdata1[0:31] Buffer size
+ * @userdata1[32:63] Transaction size
+ * @userdata2[0:31] HUID of input target
+ * @userdata2[32:63] i2c_address
+ * @devdesc Invalid read buffer size, needs to be divisible by transaction size
+ * @custdesc Internal firmware error
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ fapi2::MOD_FAPI2_EXPLR_IB_I2C_READ,
+ fapi2::RC_INVALID_BUFFER_SIZE,
+ TWO_UINT32_TO_UINT64(io_get_size,
+ I2C_TRANSACTION_SIZE),
+ TWO_UINT32_TO_UINT64(
+ TARGETING::get_huid(i_target),
+ i_i2c_addr),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ l_err->collectTrace(FAPI_TRACE_NAME);
+ io_get_size = 0; // no data being read
+ }
+ else
+ {
+ FAPI_INF("explrIbI2cRead: deviceRead() starting at i2cscom address "
+ "0x%08X for %d bytes", i_i2c_addr, io_get_size);
+
+ // keep track of total bytes read
+ size_t total_bytes_read = 0;
+
+ // Increment this address after each read transaction
+ uint64_t i2cAddr = i_i2c_addr;
+
+ // scom transaction variables
+ size_t scomTransSize = SCOM_I2C_TRANSACTION_SIZE;
+ uint8_t scomReadData[SCOM_I2C_TRANSACTION_SIZE];
+
+ // Only able to read 4 bytes at a time with i2c, so
+ // need to break into multiple i2c read transactions
+ while( total_bytes_read < io_get_size )
+ {
+ FAPI_DBG("explrIbI2cRead: deviceRead() at i2cscom address 0x%08X", i2cAddr);
+ l_err = deviceOp( DeviceFW::READ,
+ i_target,
+ scomReadData,
+ scomTransSize,
+ DEVICE_I2CSCOM_ADDRESS(i2cAddr) );
+ if (l_err)
+ {
+ FAPI_ERR("explrIbI2cRead: target 0x%08X deviceRead() at address 0x%08X failed",
+ TARGETING::get_huid(i_target), i2cAddr);
+ l_err->collectTrace(FAPI_TRACE_NAME);
+ break;
+ }
+ else
+ {
+ FAPI_DBG("explrIbI2cRead: read %02X%02X%02X%02X",
+ scomReadData[4], scomReadData[5], scomReadData[6], scomReadData[7]);
+ }
+
+ // The MMIO hardware does this byteswap for us, since we are
+ // running this over i2c we must reorder the bytes here
+ io_data_read[total_bytes_read] = scomReadData[7];
+ io_data_read[total_bytes_read+1] = scomReadData[6];
+ io_data_read[total_bytes_read+2] = scomReadData[5];
+ io_data_read[total_bytes_read+3] = scomReadData[4];
+
+ // Only able to read 4 bytes at a time
+ total_bytes_read += I2C_TRANSACTION_SIZE;
+ i2cAddr += I2C_TRANSACTION_SIZE;
+
+ // make sure this value is correct for next op
+ scomTransSize = SCOM_I2C_TRANSACTION_SIZE;
+ }
+ }
+ return l_err;
+}
+
+
+/**
+ * @brief Explorer Inband write via i2c
+ * @param[in] i_target - OCMB target
+ * @param[in] i_write_data - data to write out
+ * @param[in/out] io_write_size - how much data to write (returns how much written)
+ * @param[in] i_i2c_addr - i2c scom address
+ * @return errlHndl_t indicating success or failure
+ */
+errlHndl_t explrIbI2cWrite(TARGETING::Target * i_target,
+ const uint8_t * i_write_data,
+ size_t io_write_size,
+ const uint64_t i_i2c_addr)
+{
+ errlHndl_t l_err = nullptr;
+
+ // Verify write can be divide up evenly
+ if ( io_write_size % I2C_TRANSACTION_SIZE )
+ {
+ // invalid size expected (needs to be a multiple of I2C_TRANSACTION_SIZE)
+ FAPI_ERR("explrIbI2cWrite: write size %d is not a multiple of %d",
+ io_write_size, I2C_TRANSACTION_SIZE);
+ /*@
+ * @errortype
+ * @moduleid fapi2::MOD_FAPI2_EXPLR_IB_I2C_WRITE
+ * @reasoncode fapi2::RC_INVALID_BUFFER_SIZE
+ * @userdata1[0:31] Buffer size
+ * @userdata1[32:63] Transaction size
+ * @userdata2[0:31] HUID of input target
+ * @userdata2[32:63] i2c_address
+ * @devdesc Invalid write buffer size, needs to be divisible by transaction size
+ * @custdesc Internal firmware error
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ fapi2::MOD_FAPI2_EXPLR_IB_I2C_READ,
+ fapi2::RC_INVALID_BUFFER_SIZE,
+ TWO_UINT32_TO_UINT64(io_write_size,
+ I2C_TRANSACTION_SIZE),
+ TWO_UINT32_TO_UINT64(
+ TARGETING::get_huid(i_target),
+ i_i2c_addr),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ l_err->collectTrace(FAPI_TRACE_NAME);
+ }
+ else
+ {
+ // counter for bytes written out to SRAM space
+ size_t total_bytes_written = 0;
+
+ // going to alter this address to cycle through write data
+ uint64_t i2cAddr = i_i2c_addr;
+
+ // scom transaction variables
+ size_t scomTransSize = SCOM_I2C_TRANSACTION_SIZE;
+ uint8_t scomWriteData[SCOM_I2C_TRANSACTION_SIZE];
+
+ FAPI_INF("explrIbI2cWrite: deviceWrite() starting at i2cscom address "
+ "0x%08X for %d bytes", i_i2c_addr, io_write_size);
+
+ // Only able to write 4 bytes at a time with i2c,
+ // so need to break into multiple i2c write transactions
+ while( total_bytes_written < io_write_size )
+ {
+ memset(scomWriteData, 0x00, SCOM_I2C_TRANSACTION_SIZE);
+
+ // Only last four bytes are actually written out
+ // NOTE: MMIO hardware does this byteswap for us, but since we
+ // are running this over i2c we must reorder the bytes here
+ scomWriteData[7] = i_write_data[total_bytes_written];
+ scomWriteData[6] = i_write_data[total_bytes_written+1];
+ scomWriteData[5] = i_write_data[total_bytes_written+2];
+ scomWriteData[4] = i_write_data[total_bytes_written+3];
+
+ l_err = deviceOp( DeviceFW::WRITE,
+ i_target,
+ scomWriteData,
+ scomTransSize,
+ DEVICE_I2CSCOM_ADDRESS(i2cAddr) );
+ if (l_err)
+ {
+ FAPI_ERR("explrIbI2cWrite: i2cscom write(0x%02X%02X%02X%02X) at address 0x%08X failed",
+ scomWriteData[4], scomWriteData[5], scomWriteData[6], scomWriteData[7], i2cAddr);
+ l_err->collectTrace(FAPI_TRACE_NAME);
+ break;
+ }
+ // Really only doing 4-byte transactions
+ i2cAddr += I2C_TRANSACTION_SIZE;
+ total_bytes_written += I2C_TRANSACTION_SIZE;
+
+ // Update for next scom operation
+ scomTransSize = SCOM_I2C_TRANSACTION_SIZE;
+ }
+ }
+ return l_err;
+}
+
+/**
+ * @brief Checks if all the conditions are met to allow i2c
+ * operation instead of MMIO.
+ * @param[in] i_ocmb - OCMB target
+ * @param[in] i_mmioAddress - address passed into get/putMMIO
+ * @return true if i2c should be used instead of MMIO
+ */
+bool useI2cInsteadOfMmio( const TARGETING::Target * i_ocmb,
+ const uint64_t i_mmioAddress )
+{
+ bool useI2c = false; // default to use MMIO
+
+ uint8_t attrAllowedI2c = 0;
+
+ // Check force i2c attribute first
+ TARGETING::Target* l_sys = nullptr;
+ TARGETING::targetService().getTopLevelTarget(l_sys);
+ crit_assert(l_sys != nullptr);
+ attrAllowedI2c = l_sys->getAttr<TARGETING::ATTR_FORCE_SRAM_MMIO_OVER_I2C>();
+
+ // If not forced to use i2c, then check if that is the current scom setting
+ if (!attrAllowedI2c)
+ {
+ // The SCOM_SWITCHES attribute will keep track of when it is safe
+ // to access the ocmb via inband vs when we should do accesses over
+ // i2c. Use this attribute to decide which we want to use.
+ auto ocmb_info = i_ocmb->getAttr<TARGETING::ATTR_SCOM_SWITCHES>();
+ if (!ocmb_info.useInbandScom)
+ {
+ attrAllowedI2c = 1;
+ }
+ }
+
+ // Attribute settings must allow i2c operation before checking
+ // for a valid address range
+ if (attrAllowedI2c)
+ {
+ // Verify address is within valid SRAM range
+ if ( ((i_mmioAddress & 0x0F00000000) == EXPLR_IB_MMIO_OFFSET) &&
+ ((i_mmioAddress & 0x0FFFFFFFF) >= MIN_I2C_SRAM_SPACE_ADDRESS) &&
+ ((i_mmioAddress & 0x0FFFFFFFF) <= MAX_I2C_SRAM_SPACE_ADDRESS) )
+ {
+ useI2c = true;
+ }
+ else
+ {
+ FAPI_INF("0x%08X OCMB address 0x%.8X is outside of SRAM range so using mmio",
+ TARGETING::get_huid(i_ocmb), i_mmioAddress);
+ }
+ }
+
+ return useI2c;
+}
+
//------------------------------------------------------------------------------
// HW Communication Functions to be implemented at the platform layer.
//------------------------------------------------------------------------------
@@ -83,12 +346,22 @@ ReturnCode platGetMMIO( const Target<TARGET_TYPE_ALL>& i_target,
break; //return with error
}
- // call MMIO driver
- l_err = DeviceFW::deviceRead(l_target,
- l_data_read,
- l_get_size,
- DEVICE_MMIO_ADDRESS(i_mmioAddr, i_transSize));
-
+ // Run mmio if inband i2c isn't enabled or address is outside of SRAM range
+ if ( !useI2cInsteadOfMmio(l_target, i_mmioAddr) )
+ {
+ // call MMIO driver
+ l_err = DeviceFW::deviceRead(l_target,
+ l_data_read,
+ l_get_size,
+ DEVICE_MMIO_ADDRESS(i_mmioAddr, i_transSize));
+ }
+ else
+ {
+ // Use i2c instead of MMMIO
+ // Explorer i2c addresses are actually 32-bit and need 0xA at the beginning
+ uint64_t i2cAddr = (i_mmioAddr & 0x00000000FFFFFFFF) | EXPLR_MMIO_TO_I2C_ADDRESS_MASK;
+ l_err = explrIbI2cRead(l_target, l_data_read, l_get_size, i2cAddr);
+ }
if (l_traceit)
{
// Only trace the first 8 bytes of data read
@@ -167,11 +440,22 @@ ReturnCode platPutMMIO( const Target<TARGET_TYPE_ALL>& i_target,
std::copy(i_data.begin(), i_data.end(), l_writeDataPtr);
size_t l_dataSize = i_data.size();
- // call MMIO driver
- l_err = DeviceFW::deviceWrite(l_target,
- l_writeDataPtr,
- l_dataSize,
- DEVICE_MMIO_ADDRESS(i_mmioAddr, i_transSize));
+ // Run mmio if inband i2c isn't enabled or address is outside of SRAM range
+ if ( !useI2cInsteadOfMmio(l_target, i_mmioAddr) )
+ {
+ // call MMIO driver
+ l_err = DeviceFW::deviceWrite(l_target,
+ l_writeDataPtr,
+ l_dataSize,
+ DEVICE_MMIO_ADDRESS(i_mmioAddr, i_transSize));
+ }
+ else
+ {
+ // Address is an Explorer SRAM address, so I2C will work
+ // Explorer i2c addresses are actually 32-bit and need 0xA at the beginning
+ uint64_t i2cAddr = (i_mmioAddr & 0x00000000FFFFFFFF) | EXPLR_MMIO_TO_I2C_ADDRESS_MASK;
+ l_err = explrIbI2cWrite(l_target, l_writeDataPtr, l_dataSize, i2cAddr);
+ }
if (l_traceit)
{
// trace the first 8 bytes of written data
diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml
index cea2726d9..9b4d6764e 100644
--- a/src/usr/targeting/common/xmltohb/attribute_types.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types.xml
@@ -1805,6 +1805,21 @@
</attribute>
<attribute>
+ <id>FORCE_SRAM_MMIO_OVER_I2C</id>
+ <description>
+ Force inband SRAM access to be over I2C instead of MMIO
+ This is a way to get data when the MMIO path is not working
+ (0x00 = use normal path, 0x01 = force i2c path)
+ </description>
+ <simpleType>
+ <uint8_t/>
+ </simpleType>
+ <persistency>volatile-zeroed</persistency>
+ <readable/>
+ <writeable/>
+ </attribute>
+
+ <attribute>
<id>FREQ_CORE_CEILING_MHZ</id>
<description>
The maximum core frequency in MHz.
diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml
index c5b466ebf..bc0858b5d 100644
--- a/src/usr/targeting/common/xmltohb/target_types.xml
+++ b/src/usr/targeting/common/xmltohb/target_types.xml
@@ -1860,6 +1860,9 @@
<id>FORCE_NVDIMM_RESET</id>
</attribute>
<attribute>
+ <id>FORCE_SRAM_MMIO_OVER_I2C</id>
+ </attribute>
+ <attribute>
<id>FREQ_CORE_CEILING_MHZ</id>
</attribute>
<attribute>
OpenPOWER on IntegriCloud