From 165bb46bac36d2774b7fe36543024710053ec3d0 Mon Sep 17 00:00:00 2001 From: Matt Derksen Date: Thu, 30 Aug 2018 08:10:40 -0500 Subject: Support fapi2 i2c functions New interface in fapi2 to perform i2c operations directly. This is needed for OCMB access before we get OMI bus running, specifically as part of a cmd/rsp protocol. Change-Id: I8b778f12f8c0c6820ceb51146f1e21d30891c964 RTC:197029 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/63919 Tested-by: Jenkins Server Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Tested-by: FSP CI Jenkins Reviewed-by: Christian R. Geddes Reviewed-by: Corey V. Swenson Reviewed-by: Daniel M. Crowell --- src/usr/fapi2/plat_i2c_access.C | 261 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 src/usr/fapi2/plat_i2c_access.C (limited to 'src/usr/fapi2/plat_i2c_access.C') diff --git a/src/usr/fapi2/plat_i2c_access.C b/src/usr/fapi2/plat_i2c_access.C new file mode 100644 index 000000000..a17d013b0 --- /dev/null +++ b/src/usr/fapi2/plat_i2c_access.C @@ -0,0 +1,261 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/fapi2/plat_i2c_access.C $ */ +/* */ +/* 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 plat_i2c_access.C + * + * @brief Implements FAPI i2c functions at the platform layer. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace fapi2 +{ + +//------------------------------------------------------------------------------ +// HW Communication Functions to be implemented at the platform layer. +//------------------------------------------------------------------------------ + +/// @brief Platform-level implementation called by FAPI getI2c() +ReturnCode platGetI2c( const Target& i_target, + const size_t i_get_size, + const std::vector& i_cfgData, + std::vector& o_data ) +{ + ReturnCode l_rc; + errlHndl_t l_err = nullptr; + + FAPI_DBG(ENTER_MRK "platGetI2c"); + // Note: Trace is placed here in plat code because PPE doesn't support + // trace in common fapi2_i2c_access.H + bool l_traceit = platIsScanTraceEnabled(); + + // Grab the name of the target + TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; + fapi2::toString(i_target, l_targName, sizeof(l_targName)); + + + size_t l_get_size = i_get_size; // need non-const + + // create a temporary buffer for read data + uint8_t * l_data_read = new uint8_t[ l_get_size ]; + + do + { + // Extract the component pointer + TARGETING::Target * l_target = nullptr; + l_err = fapi2::platAttrSvc::getTargetingTarget(i_target, l_target); + if ( l_err ) + { + FAPI_ERR( "platGetI2c: Error from getTargetingTarget on %s", + l_targName ); + break; //return with error + } + + // Perform i2c read + uint64_t l_traceCfgData = 0; + + if ( i_cfgData.empty() ) + { + l_err = deviceRead( + l_target, + l_data_read, + l_get_size, + DEVICE_FAPI_I2C_ADDRESS() + ); + } + else + { + // deviceRead() requires data pointer + // copy data from const vector to data ptr + uint8_t * l_configDataPtr = new uint8_t[ i_cfgData.size() ]; + std::copy(i_cfgData.begin(), i_cfgData.end(), l_configDataPtr); + + // if trace is enabled, + // save the config data into l_traceCfgData variable + if (l_traceit) + { + // copy the first 8 bytes of config data into trace variable + if (i_cfgData.size() >= sizeof(l_traceCfgData)) + { + // only copy what fits into l_traceCfgData variable + memcpy(&l_traceCfgData, l_configDataPtr,sizeof(l_traceCfgData)); + } + else + { + // all the config data bytes fit into l_traceCfgData variable + memcpy(&l_traceCfgData, l_configDataPtr, i_cfgData.size()); + } + } + + l_err = deviceRead( + l_target, + l_data_read, + l_get_size, + DEVICE_FAPI_I2C_ADDRESS_WCONFIG(i_cfgData.size(), + l_configDataPtr) + ); + + delete [] l_configDataPtr; + } + + if (l_err) + { + FAPI_ERR("platGetI2c: error from FAPI_I2C deviceRead() of target %s" + , l_targName ); + } + + if (l_traceit) + { + // Only trace the first 8 bytes of data read + // (don't want to overflow trace buffer) + uint64_t l_traceDataRead = 0; + if (l_get_size >= sizeof(l_traceDataRead)) + { + memcpy(&l_traceDataRead, l_data_read, sizeof(l_traceDataRead)); + } + else if (l_get_size > 0) + { + memcpy(&l_traceDataRead, l_data_read, l_get_size); + } + if ( i_cfgData.empty() ) + { + FAPI_SCAN("TRACE : GETI2C : %s : %d %.16llX", + l_targName, + l_get_size, + l_traceDataRead); + } + else + { + FAPI_SCAN("TRACE : GETI2C w/config %.16llX : %s : %d %.16llX", + l_traceCfgData, + l_targName, + l_get_size, + l_traceDataRead); + } + } + + } while(0); + + if (l_err) + { + l_rc.setPlatDataPtr(reinterpret_cast (l_err)); + } + else + { + // read was successful so copy data into o_data + o_data.clear(); + o_data.insert( o_data.end(), + &l_data_read[0], + &l_data_read[l_get_size] ); + } + + // cleanup allocated memory + delete [] l_data_read; + + FAPI_DBG(EXIT_MRK "platGetI2c"); + return l_rc; +} + +/// @brief Platform-level implementation called by FAPI putI2c() +ReturnCode platPutI2c(const Target& i_target, + const std::vector& i_data) +{ + ReturnCode l_rc; + errlHndl_t l_err = nullptr; + + FAPI_DBG(ENTER_MRK "platPutI2c"); + // Note: Trace is placed here in plat code because PPE doesn't support + // trace in common fapi2_i2c_access.H + bool l_traceit = platIsScanTraceEnabled(); + + // Grab the name of the target + TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; + fapi2::toString(i_target, l_targName, sizeof(l_targName)); + + do { + // Extract the component pointer + TARGETING::Target * l_target = nullptr; + l_err = fapi2::platAttrSvc::getTargetingTarget(i_target, l_target); + if (l_err) + { + FAPI_ERR( "platPutI2c: Error from getTargetingTarget on %s", + l_targName ); + break; //return with error + } + + //copy data from const vector to data ptr + uint8_t * l_dataPtr = new uint8_t[ i_data.size() ]; + std::copy(i_data.begin(), i_data.end(), l_dataPtr); + size_t l_dataSize = i_data.size(); + + l_err = deviceWrite( l_target, + l_dataPtr, + l_dataSize, + DEVICE_FAPI_I2C_ADDRESS() ); + if (l_traceit) + { + // trace the first 8 bytes of written data + // (avoid trace buffer overflow) + uint64_t traceWriteData = 0; + if (l_dataSize > sizeof(traceWriteData)) + { + // copy what will fit into traceWriteData variable + memcpy(&traceWriteData, l_dataPtr, sizeof(traceWriteData)); + } + else + { + memcpy(&traceWriteData, l_dataPtr, l_dataSize); + } + FAPI_SCAN( "TRACE : PUTI2C : %s : %d %.16llX", + l_targName, + l_dataSize, + traceWriteData ); + } + + delete [] l_dataPtr; + + } while (0); + + if (l_err) + { + l_rc.setPlatDataPtr(reinterpret_cast (l_err)); + } + + FAPI_DBG(EXIT_MRK "platPutI2c"); + return l_rc; +} + +} // End namespace -- cgit v1.2.1