diff options
author | Matt Derksen <mderkse1@us.ibm.com> | 2018-08-30 08:10:40 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2018-09-20 17:06:38 -0500 |
commit | 165bb46bac36d2774b7fe36543024710053ec3d0 (patch) | |
tree | f21eb63d24214397c161e76641ee6ef4c1added0 /src/usr/fapi2/plat_i2c_access.C | |
parent | 5abc57bc8352ef13ab7aa23edfbc2d607f9cd5b2 (diff) | |
download | talos-hostboot-165bb46bac36d2774b7fe36543024710053ec3d0.tar.gz talos-hostboot-165bb46bac36d2774b7fe36543024710053ec3d0.zip |
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 <pfd-jenkins+hostboot@us.ibm.com>
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: Christian R. Geddes <crgeddes@us.ibm.com>
Reviewed-by: Corey V. Swenson <cswenson@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/fapi2/plat_i2c_access.C')
-rw-r--r-- | src/usr/fapi2/plat_i2c_access.C | 261 |
1 files changed, 261 insertions, 0 deletions
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 <stdint.h> +#include <errl/errlentry.H> +#include <devicefw/userif.H> +#include <return_code.H> +#include <target.H> +#include <target_types.H> +#include <plat_utils.H> +#include <attribute_service.H> +#include <hwpf_fapi2_reasoncodes.H> +#include <fapi2/plat_i2c_access.H> + + + +namespace fapi2 +{ + +//------------------------------------------------------------------------------ +// HW Communication Functions to be implemented at the platform layer. +//------------------------------------------------------------------------------ + +/// @brief Platform-level implementation called by FAPI getI2c() +ReturnCode platGetI2c( const Target<TARGET_TYPE_ALL>& i_target, + const size_t i_get_size, + const std::vector<uint8_t>& i_cfgData, + std::vector<uint8_t>& 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<void *> (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<TARGET_TYPE_ALL>& i_target, + const std::vector<uint8_t>& 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<void *> (l_err)); + } + + FAPI_DBG(EXIT_MRK "platPutI2c"); + return l_rc; +} + +} // End namespace |