diff options
-rw-r--r-- | src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H | 3 | ||||
-rw-r--r-- | src/usr/expaccess/test/exptest_utils.C | 30 | ||||
-rw-r--r-- | src/usr/expaccess/test/exptest_utils.H | 6 | ||||
-rw-r--r-- | src/usr/expaccess/test/ocmbcommtest.H | 146 | ||||
-rw-r--r-- | src/usr/fapi2/plat_mmio_access.C | 310 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/attribute_types.xml | 15 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/target_types.xml | 3 |
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> |