summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/utils
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2017-03-13 23:20:17 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-03-18 10:31:54 -0400
commitdb18489a8cf55c2b3f01e98577ec2be5c3045aa6 (patch)
tree9327208cbe1f01612d8a7ad4f842ebc754b268c6 /src/import/generic/memory/lib/utils
parent5475af82e4c545f9a262b5bbe544504ba41d5e75 (diff)
downloadtalos-hostboot-db18489a8cf55c2b3f01e98577ec2be5c3045aa6.tar.gz
talos-hostboot-db18489a8cf55c2b3f01e98577ec2be5c3045aa6.zip
Move scom API to share among controllers
Change-Id: I3b3d0bf72f5b52a49c6ea9d09ed91dfbf9613b1b Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/37882 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Brian R. Silver <bsilver@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/38017 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/generic/memory/lib/utils')
-rw-r--r--src/import/generic/memory/lib/utils/scom.H387
1 files changed, 387 insertions, 0 deletions
diff --git a/src/import/generic/memory/lib/utils/scom.H b/src/import/generic/memory/lib/utils/scom.H
new file mode 100644
index 000000000..314623e3f
--- /dev/null
+++ b/src/import/generic/memory/lib/utils/scom.H
@@ -0,0 +1,387 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/utils/scom.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* [+] 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 scom.H
+/// @brief Tools related to scom operations
+///
+// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_SCOM_H_
+#define _MSS_SCOM_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/c_str.H>
+
+//
+// Wrapping scom operations: We wrap fapi2::get/putScom for two reasons. The
+// first is so that we can hook in to the base scom operations in the lab. This
+// is expected to be used for test tracking and data gathering. The other
+// reason is to facilitate sharing code with Z in the event they don't leverage
+// fapi2. This gives us a place to define a common "hw access" API allowing
+// P and Z to implement the underlying firmware API using different mechanisms.
+//
+
+namespace mss
+{
+
+/// @brief Reads a SCOM register from a chip.
+/// @tparam K template parameter, passed in target.
+/// @param[in] i_target HW target to operate on.
+/// @param[in] i_address SCOM register address to read from.
+/// @param[out] o_data Buffer that holds data read from HW target.
+/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
+/// @note We wrap scom operations in the mss library so that we can hook
+/// into them in the lab. For IPL firmware, this should compile out.
+template< fapi2::TargetType K >
+inline fapi2::ReturnCode getScom(const fapi2::Target<K>& i_target,
+ const uint64_t i_address,
+ fapi2::buffer<uint64_t>& o_data)
+{
+#ifdef PSYSTEMS_MSS_LAB_ONLY
+ // Place holder for lab-hooks
+ return fapi2::getScom(i_target, i_address, o_data);
+#else
+ return fapi2::getScom(i_target, i_address, o_data);
+#endif
+}
+
+/// @brief Writes a SCOM register on a chip.
+/// @tparam K template parameter, passed in target.
+/// @param[in] i_target HW target to operate on.
+/// @param[in] i_address SCOM register address to write to.
+/// @param[in] i_data Buffer that holds data to write into address.
+/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
+/// @note We wrap scom operations in the mss library so that we can hook
+/// into them in the lab. For IPL firmware, this should compile out.
+template< fapi2::TargetType K >
+inline fapi2::ReturnCode putScom(const fapi2::Target<K>& i_target,
+ const uint64_t i_address,
+ const fapi2::buffer<uint64_t> i_data)
+{
+#ifdef PSYSTEMS_MSS_LAB_ONLY
+ // Place holder for lab-hooks
+ return fapi2::putScom(i_target, i_address, i_data);
+#else
+ return fapi2::putScom(i_target, i_address, i_data);
+#endif
+}
+
+/// @brief Writes a SCOM register under mask on a chip
+/// @tparam K template parameter, passed in target.
+/// @param[in] i_target HW target to operate on.
+/// @param[in] i_address SCOM register address to write to.
+/// @param[in] i_data Buffer that holds data to write into address.
+/// @param[in] i_mask Buffer that holds the mask value.
+/// @return fapi2::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
+/// @note We wrap scom operations in the mss library so that we can hook
+/// into them in the lab. For IPL firmware, this should compile out.
+template< fapi2::TargetType K >
+inline fapi2::ReturnCode putScomUnderMask(const fapi2::Target<K>& i_target,
+ const uint64_t i_address,
+ const fapi2::buffer<uint64_t> i_data,
+ const fapi2::buffer<uint64_t> i_mask)
+{
+#ifdef PSYSTEMS_MSS_LAB_ONLY
+ // Place holder for lab-hooks
+ return fapi2::putScomUnderMask(i_target, i_address, i_data, i_mask);
+#else
+ return fapi2::putScomUnderMask(i_target, i_address, i_data, i_mask);
+#endif
+}
+
+///
+/// @brief Blast one peice of data across a vector of addresses
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addrs const std::vector<uint64_t>& addresses
+/// @param[in] i_data const fapi2::buffer<uint64_t>& the data to blast
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note Author is originally from Boston (Pahk mah cah in Havahd Yahd)
+
+/// @note std::transform might have been tidier, but because of the ReturnCode
+/// and the FAPI_TRY mechanism, this is the simplest.
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_target,
+ const std::vector<uint64_t>& i_addrs,
+ const fapi2::buffer<uint64_t>& i_data )
+{
+ size_t count(0);
+
+ for (const auto& a : i_addrs)
+ {
+ FAPI_TRY( mss::putScom(i_target, a, i_data) );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "scom_blastah failed: %d of %d executed against %s", count, i_addrs.size(), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief Blast one peice of data across a vector of targets
+/// @param[in] i_targets the vector of targets for the scom
+/// @param[in] i_addr the address
+/// @param[in] i_data const fapi2::buffer<uint64_t>& the data to blast
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_blastah( const std::vector<fapi2::Target<T> >& i_targets,
+ const uint64_t i_addr,
+ const fapi2::buffer<uint64_t>& i_data )
+{
+ size_t count(0);
+
+ for (const auto& t : i_targets)
+ {
+ FAPI_TRY( mss::putScom(t, i_addr, i_data) );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no targets in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "scom_blastah failed: %d of %d written to 0x%llx", count, i_targets.size(), i_addr);
+ return fapi2::current_err;
+}
+
+///
+/// @brief Blast one peice of data across a vector of targets
+/// @param[in] i_targets the vector of targets for the scom
+/// @param[in] i_addrs the vector of addresses
+/// @param[in] i_data const fapi2::buffer<uint64_t>& the data to blast
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_blastah( const std::vector<fapi2::Target<T> >& i_targets,
+ const std::vector<uint64_t>& i_addrs,
+ const fapi2::buffer<uint64_t>& i_data )
+{
+ size_t count(0);
+
+ for (const auto& t : i_targets)
+ {
+ FAPI_TRY( mss::scom_blastah(t, i_addrs, i_data) );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no targets in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "scom_blastah failed: %d of %dx%d", count, i_targets.size(), i_addrs.size() );
+ return fapi2::current_err;
+}
+
+///
+/// @brief Blast parallel vectors of data and addresses to a single target
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addrs const std::vector<uint64_t>& addresses
+/// @param[in] i_data std:vector<fapi2::buffer<uint64_t>>& the data to blast
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_targets,
+ const std::vector<uint64_t>& i_addrs,
+ const std::vector<fapi2::buffer<uint64_t>>& i_data )
+{
+ size_t count(0);
+
+ // Little sanity check
+ if (i_data.size() != i_addrs.size())
+ {
+ FAPI_ERR("Passed bad vectors in to scom_blastah: %d and %d in size", i_data.size(), i_addrs.size() );
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ }
+
+ auto l_address = i_addrs.begin();
+ auto l_data = i_data.begin();
+
+ for ( ; l_address != i_addrs.end(); ++l_address, ++l_data )
+ {
+ FAPI_TRY( mss::putScom(i_targets, *l_address, *l_data) );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "parallel scom_blastah failed: %d of %d", count, i_addrs.size() );
+ return fapi2::current_err;
+}
+
+///
+/// @brief Blast parallel vectors of data and address pairs to a single target
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addrs const std::vector<uint64_t>& of address pairs
+/// @param[in] i_data std::vector< std::pair<uint64_t, uint64_t>> the data to blast
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_targets,
+ const std::vector< std::pair< uint64_t, uint64_t> >& i_addrs,
+ const std::vector< std::pair<fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> > >& i_data )
+{
+ size_t count(0);
+
+ // Little sanity check
+ if (i_data.size() != i_addrs.size())
+ {
+ FAPI_ERR("Passed bad vectors of pairs in to scom_blastah: %d and %d in size", i_data.size(), i_addrs.size() );
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ }
+
+ auto l_address = i_addrs.begin();
+ auto l_data = i_data.begin();
+
+ for ( ; l_address != i_addrs.end(); ++l_address, ++l_data )
+ {
+ FAPI_TRY( mss::putScom(i_targets, l_address->first, l_data->first) );
+ FAPI_TRY( mss::putScom(i_targets, l_address->second, l_data->second) );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "parallel pairs scom_blastah failed: %d of %d", count, i_addrs.size() );
+ return fapi2::current_err;
+}
+
+///
+/// @brief Blast single data data to a vector of address pairs to a single target
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addrs const std::vector< std::pair<uint64_t, uint64_t> >& of address pairs
+/// @param[in] i_data uint64_t the data to blast
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_targets,
+ const std::vector< std::pair< uint64_t, uint64_t> >& i_addr,
+ const fapi2::buffer<uint64_t>& i_data )
+{
+ size_t count(0);
+
+ for (auto a = i_addr.begin(); a != i_addr.end(); ++a)
+ {
+ FAPI_TRY( mss::putScom(i_targets, a->first, i_data) );
+ FAPI_TRY( mss::putScom(i_targets, a->second, i_data) );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "pairs scom_blastah failed: %d of %d", count, i_addr.size() );
+ return fapi2::current_err;
+}
+
+///
+/// @brief Suck one peice of data from a vector of addresses
+/// @tparam T the fapi2::TargetType of the target
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addr the vector of addresses
+/// @param[in] o_data std::vector<uint64_t> the resulting data
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note Author is originally from Boston (Pahk mah cah in Havahd Yahd)
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_suckah( const fapi2::Target<T>& i_target,
+ const std::vector<uint64_t>& i_addr,
+ std::vector< fapi2::buffer<uint64_t> >& o_data )
+{
+ size_t count(0);
+ fapi2::buffer<uint64_t> l_read;
+
+ o_data.clear();
+
+ for (const auto& a : i_addr)
+ {
+ FAPI_TRY( mss::getScom(i_target, a, l_read) );
+ o_data.push_back(l_read);
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "scom_suckah failed: %d of %d executed against %s", count, i_addr.size(), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Suck one peice of data from a vector of address pairs
+/// @tparam T the fapi2::TargetType of the target
+/// @tparam B a begin iterator
+/// @tparam E an end iterator
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addr a vector of address pairs
+/// @param[in] o_data std::vector< std::pair<uint64_t, uint64_t>> the resulting data
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note Author is originally from Boston (Pahk mah cah in Havahd Yahd)
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_suckah( const fapi2::Target<T>& i_target,
+ const std::vector< std::pair< uint64_t, uint64_t> >& i_addr,
+ std::vector< std::pair<fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> > >& o_data )
+{
+ size_t count(0);
+ std::pair< fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> > l_read;
+
+ o_data.clear();
+
+ for (const auto& a : i_addr)
+ {
+ FAPI_TRY( mss::getScom(i_target, a.first, l_read.first) );
+ FAPI_TRY( mss::getScom(i_target, a.second, l_read.second) );
+ o_data.push_back( l_read );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "scom_suckah failed: %d of %d executed against %s", count, i_addr.size(), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+
+}
+#endif
OpenPOWER on IntegriCloud