diff options
author | Corey Swenson <cswenson@us.ibm.com> | 2015-01-27 09:05:37 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2015-02-18 15:12:13 -0600 |
commit | 417c6e0a4bb7c8f9d9721b73ddcae696007be15e (patch) | |
tree | 42778d629a19bf85f740cbd649ca2d27d8a20aa9 /src/usr | |
parent | 79ea7abf6d31c146c680d39b9f3ae007e434a573 (diff) | |
download | blackbird-hostboot-417c6e0a4bb7c8f9d9721b73ddcae696007be15e.tar.gz blackbird-hostboot-417c6e0a4bb7c8f9d9721b73ddcae696007be15e.zip |
HBRT Runtime VPD Updates
Enables writes to VPD and handles disabling
PNOR cache in manufacturing mode
Change-Id: I03d4246ceb91520939f8b04f3b3d2fc31c116079
RTC: 114911
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15462
Tested-by: Jenkins Server
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr')
-rwxr-xr-x | src/usr/i2c/eepromdd.C | 8 | ||||
-rw-r--r-- | src/usr/i2c/errlud_i2c.H | 6 | ||||
-rwxr-xr-x | src/usr/i2c/i2c.H | 37 | ||||
-rw-r--r-- | src/usr/i2c/i2c.mk | 27 | ||||
-rw-r--r-- | src/usr/i2c/i2c_common.H | 84 | ||||
-rw-r--r-- | src/usr/i2c/makefile | 11 | ||||
-rw-r--r-- | src/usr/i2c/runtime/makefile | 39 | ||||
-rwxr-xr-x | src/usr/i2c/runtime/rt_i2c.C | 224 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/attribute_types_hb.xml | 4 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.C | 35 | ||||
-rw-r--r-- | src/usr/vpd/ipvpd.H | 5 | ||||
-rw-r--r-- | src/usr/vpd/rtvpd_load.C | 103 | ||||
-rw-r--r-- | src/usr/vpd/runtime/makefile | 7 | ||||
-rw-r--r-- | src/usr/vpd/runtime/rt_vpd.C | 167 | ||||
-rw-r--r-- | src/usr/vpd/spd.C | 178 | ||||
-rwxr-xr-x | src/usr/vpd/spd.H | 5 | ||||
-rwxr-xr-x | src/usr/vpd/vpd.C | 17 | ||||
-rw-r--r-- | src/usr/vpd/vpd.H | 6 |
18 files changed, 787 insertions, 176 deletions
diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C index 317065c75..b0482f6f0 100755 --- a/src/usr/i2c/eepromdd.C +++ b/src/usr/i2c/eepromdd.C @@ -46,10 +46,13 @@ #include <i2c/eepromddreasoncodes.H> #include <i2c/eepromif.H> #include <i2c/i2creasoncodes.H> -#include <i2c/i2cif.H> #include "eepromdd.H" #include "errlud_i2c.H" +#ifndef __HOSTBOOT_RUNTIME +#include <i2c/i2cif.H> +#endif + // ---------------------------------------------- // Globals // ---------------------------------------------- @@ -254,6 +257,7 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType, return err; } // end eepromPerformOp +#ifndef __HOSTBOOT_RUNTIME //------------------------------------------------------------------- //eepromPresence //------------------------------------------------------------------- @@ -315,7 +319,7 @@ bool eepromPresence ( TARGETING::Target * i_target ) TRACDCOMP(g_trac_eeprom, EXIT_MRK"eepromPresence()"); return l_present; } - +#endif // ------------------------------------------------------------------ diff --git a/src/usr/i2c/errlud_i2c.H b/src/usr/i2c/errlud_i2c.H index ee97f8e46..7cea03b6e 100644 --- a/src/usr/i2c/errlud_i2c.H +++ b/src/usr/i2c/errlud_i2c.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* [+] 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. */ @@ -31,7 +33,7 @@ #include <errl/errluserdetails.H> #include <devicefw/driverif.H> -#include "i2c.H" +#include "i2c_common.H" #include "eepromdd.H" namespace I2C diff --git a/src/usr/i2c/i2c.H b/src/usr/i2c/i2c.H index 334532a53..c3e52785a 100755 --- a/src/usr/i2c/i2c.H +++ b/src/usr/i2c/i2c.H @@ -37,6 +37,7 @@ // ---------------------------------------------- #include <errl/errlentry.H> #include <sys/time.h> +#include "i2c_common.H" namespace I2C { @@ -162,42 +163,6 @@ enum i2c_reg_offset_t }; - -/** - * @brief Structure used to pass important variables between functions - */ -struct misc_args_t -{ - uint8_t port; - uint8_t engine; - uint64_t devAddr; - bool skip_mode_setup; - bool with_stop; - bool read_not_write; - uint64_t bus_speed; // in kbits/sec (ie 400KHz) - uint16_t bit_rate_divisor; // uint16_t to match size in mode register - uint64_t polling_interval_ns; // in nanoseconds - uint64_t timeout_count; - uint64_t offset_length; - uint8_t* offset_buffer; - - TARGETING::I2cSwitches switches; - - misc_args_t():port(0xFF), - engine(0xFF), - devAddr(0xFFFFFFFF), - skip_mode_setup(false), - with_stop(true), - read_not_write(true), - bus_speed(0), - bit_rate_divisor(0), - polling_interval_ns(0), - timeout_count(0), - offset_length(0), - offset_buffer(NULL){}; - -}; - /** * @brief I2C FIFO register definition */ diff --git a/src/usr/i2c/i2c.mk b/src/usr/i2c/i2c.mk new file mode 100644 index 000000000..33d2accda --- /dev/null +++ b/src/usr/i2c/i2c.mk @@ -0,0 +1,27 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/i2c/i2c.mk $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2015 +# [+] 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 +# common objects with runtime +OBJS += eepromdd.o +OBJS += errlud_i2c.o diff --git a/src/usr/i2c/i2c_common.H b/src/usr/i2c/i2c_common.H new file mode 100644 index 000000000..68865a50d --- /dev/null +++ b/src/usr/i2c/i2c_common.H @@ -0,0 +1,84 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/i2c/i2c.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* [+] 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 */ +#ifndef __I2C_COMMON_H +#define __I2C_COMMON_H + +// Handy macros to check i2c ranges +// Pass in an instance of a TARGETING::ATTR_I2C_BUS_SPEED_ARRAY_type +#define I2C_BUS_MAX_ENGINE(var) (sizeof(var)/sizeof(var[0])) +#define I2C_BUS_MAX_PORT(var) (sizeof(var[0])/sizeof(var[0][0])) + +/** + * @file i2c_common.H + * + * @brief Provides the interfaces for the i2c device driver common with runtime + * + */ + +// ---------------------------------------------- +// Includes +// ---------------------------------------------- + +namespace I2C +{ + +/** + * @brief Structure used to pass important variables between functions + */ +struct misc_args_t +{ + uint8_t port; + uint8_t engine; + uint64_t devAddr; + bool skip_mode_setup; + bool with_stop; + bool read_not_write; + uint64_t bus_speed; // in kbits/sec (ie 400KHz) + uint16_t bit_rate_divisor; // uint16_t to match size in mode register + uint64_t polling_interval_ns; // in nanoseconds + uint64_t timeout_count; + uint64_t offset_length; + uint8_t* offset_buffer; + + TARGETING::I2cSwitches switches; + + misc_args_t():port(0xFF), + engine(0xFF), + devAddr(0xFFFFFFFF), + skip_mode_setup(false), + with_stop(true), + read_not_write(true), + bus_speed(0), + bit_rate_divisor(0), + polling_interval_ns(0), + timeout_count(0), + offset_length(0), + offset_buffer(NULL){}; + +}; + +}; // end I2C namespace + +#endif // __I2C_COMMON_H diff --git a/src/usr/i2c/makefile b/src/usr/i2c/makefile index 17105ea79..f3c47daec 100644 --- a/src/usr/i2c/makefile +++ b/src/usr/i2c/makefile @@ -5,7 +5,9 @@ # # OpenPOWER HostBoot Project # -# COPYRIGHT International Business Machines Corp. 2011,2014 +# Contributors Listed Below - COPYRIGHT 2011,2015 +# [+] 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. @@ -23,10 +25,13 @@ ROOTPATH = ../../.. MODULE = i2c +#include common objects between hb and runtime +include i2c.mk + +#include unique objects OBJS += i2c.o -OBJS += eepromdd.o -OBJS += errlud_i2c.o SUBDIRS += test.d +SUBDIRS += runtime.d include ${ROOTPATH}/config.mk diff --git a/src/usr/i2c/runtime/makefile b/src/usr/i2c/runtime/makefile new file mode 100644 index 000000000..e6bf9330b --- /dev/null +++ b/src/usr/i2c/runtime/makefile @@ -0,0 +1,39 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/vpd/runtime/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2013,2015 +# [+] 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 +# common objects with runtime +HOSTBOOT_RUNTIME = 1 +ROOTPATH = ../../../.. +MODULE = i2c_rt + +#include common objects between hostboot and runtime hostboot +include ../i2c.mk + +#add unique object modules +OBJS += rt_i2c.o + +VPATH += .. + +include $(ROOTPATH)/config.mk + diff --git a/src/usr/i2c/runtime/rt_i2c.C b/src/usr/i2c/runtime/rt_i2c.C new file mode 100755 index 000000000..9938ebe19 --- /dev/null +++ b/src/usr/i2c/runtime/rt_i2c.C @@ -0,0 +1,224 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/i2c/runtime/rt_i2c.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015 */ +/* [+] 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 rt_i2c.C + * + * @brief Runtime implementation of the i2c device driver + * + */ + +// ---------------------------------------------- +// Includes +// ---------------------------------------------- +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <errl/errludtarget.H> +#include <devicefw/driverif.H> +#include <i2c/i2creasoncodes.H> +#include <runtime/interface.h> +#include <runtime/rt_targeting.H> +#include "../errlud_i2c.H" + +// ---------------------------------------------- +// Trace definitions +// ---------------------------------------------- +trace_desc_t* g_trac_i2c = NULL; +TRAC_INIT( & g_trac_i2c, I2C_COMP_NAME, KILOBYTE ); + +// Easy macro replace for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) + + +namespace I2C +{ + +// ------------------------------------------------------------------ +// i2cPerformOp +// ------------------------------------------------------------------ +errlHndl_t i2cPerformOp( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, + void * io_buffer, + size_t & io_buflen, + int64_t i_accessType, + va_list i_args ) +{ + errlHndl_t err = NULL; + + // Get the args out of the va_list + // Address, Port, Engine, Device Addr. + // Other args set below + misc_args_t args; + args.port = va_arg( i_args, uint64_t ); + args.engine = va_arg( i_args, uint64_t ); + args.devAddr = va_arg( i_args, uint64_t ); + + // These are additional parms in the case an offset is passed in + // via va_list, as well + + uint64_t offset_length = va_arg( i_args, uint64_t); + uint64_t offset_buffer = 0; + + if ( offset_length != 0 ) + { + offset_buffer = va_arg(i_args, uint64_t); + } + + int rc = 0; + bool l_host_if_enabled = true; + RT_TARG::rtChipId_t proc_id = 0; + + // Convert target to proc id + err = RT_TARG::getRtTarget( i_target, + proc_id); + if(err) + { + return err; + } + + // Combine proc/engine/port + uint64_t proc_engine_port = 0; + proc_engine_port |= proc_id << HBRT_I2C_MASTER_CHIP_SHIFT; + proc_engine_port |= (uint64_t)(args.engine) << HBRT_I2C_MASTER_ENGINE_SHIFT; + proc_engine_port |= (uint64_t)(args.port) << HBRT_I2C_MASTER_PORT_SHIFT; + + if(i_opType == DeviceFW::READ) + { + if(g_hostInterfaces->i2c_read != NULL) + { + rc = g_hostInterfaces->i2c_read + ( + proc_engine_port, // Master Chip/Engine/Port + args.devAddr, // Dev Addr + offset_length, // Offset size + offset_buffer, // Offset + io_buflen, // Buffer length + io_buffer // Buffer + ); + } + else + { + TRACFCOMP(g_trac_i2c,ERR_MRK"Hypervisor I2C read interface not linked"); + l_host_if_enabled = false; + } + } + else if (i_opType == DeviceFW::WRITE) + { + if(g_hostInterfaces->i2c_write != NULL) + { + rc = g_hostInterfaces->i2c_write + ( + proc_engine_port, // Master Chip/Engine/Port + args.devAddr, // Dev Addr + offset_length, // Offset size + offset_buffer, // Offset + io_buflen, // Buffer length + io_buffer // Buffer + ); + } + else + { + TRACFCOMP(g_trac_i2c,ERR_MRK"Hypervisor I2C write interface not linked"); + l_host_if_enabled = false; + } + } + + if(!l_host_if_enabled) + { + /*@ + * @errortype + * @moduleid I2C_PERFORM_OP + * @reasoncode I2C_RUNTIME_INTERFACE_ERR + * @userdata1 0 + * @userdata2 Op type + * @devdesc I2C read/write interface not linked. + */ + err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL, + I2C_PERFORM_OP, + I2C_RUNTIME_INTERFACE_ERR, + 0, + i_opType); + + err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH); + } + + if(rc) + { + // convert rc to error log + /*@ + * @errortype + * @moduleid I2C_PERFORM_OP + * @reasoncode I2C_RUNTIME_ERR + * @userdata1 Hypervisor return code + * @userdata2 Op type + * @devdesc I2C access error + */ + err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_INFORMATIONAL, + I2C_PERFORM_OP, + I2C_RUNTIME_ERR, + rc, + i_opType); + + err->addHwCallout(i_target, + HWAS::SRCI_PRIORITY_LOW, + HWAS::NO_DECONFIG, + HWAS::GARD_NULL); + + // Note: no trace buffer available at runtime + } + + // If there is an error, add parameter info to log + if ( err != NULL ) + { + I2C::UdI2CParms( i_opType, + i_target, + io_buflen, + i_accessType, + args ) + .addToLog(err); + } + + TRACDCOMP( g_trac_i2c, + EXIT_MRK"i2cPerformOp() - %s", + ((NULL == err) ? "No Error" : "With Error") ); + + return err; +} // end i2cPerformOp + +// Register the generic I2C perform Op with the routing code for Procs. +DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, + DeviceFW::I2C, + TARGETING::TYPE_PROC, + i2cPerformOp ); + +// Register the generic I2C perform Op with the routing code for Memory Buffers. +DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, + DeviceFW::I2C, + TARGETING::TYPE_MEMBUF, + i2cPerformOp ); + +} // end namespace I2C diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml index 5b2922fe7..75b19c795 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml @@ -743,9 +743,9 @@ <complexType> <description>VPD flags</description> <field> - <name>pnorLoaded</name> + <name>pnorCacheValid</name> <description>Set when this target's VPD data has been loaded - into the PNOR. + from EEPROM into the PNOR. </description> <type>uint8_t</type> <bits>1</bits> diff --git a/src/usr/vpd/ipvpd.C b/src/usr/vpd/ipvpd.C index 57d5a9ce8..af0055cd1 100644 --- a/src/usr/vpd/ipvpd.C +++ b/src/usr/vpd/ipvpd.C @@ -242,7 +242,7 @@ errlHndl_t IpVpdFacade::write ( TARGETING::Target * i_target, // PNOR needs to be loaded before we can write it TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches = i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>(); - if( vpdSwitches.pnorLoaded ) + if( vpdSwitches.pnorCacheValid ) { l_args.location = VPD::PNOR; err = write( i_target, @@ -811,8 +811,8 @@ errlHndl_t IpVpdFacade::findRecordOffset ( const char * i_record, * @moduleid VPD::VPD_IPVPD_FIND_RECORD_OFFSET * @userdata1[0:31] Target HUID * @userdata1[32:63] Requested VPD Source Location - * @userdata2[0:31] CONFIG_<vpd>_READ_WRITE_CONFIG_PNOR - * @userdata2[32:63] CONFIG_<vpd>_READ_WRITE_CONFIG_HW + * @userdata2[0:31] VPD write PNOR flag + * @userdata2[32:63] VPD write HW flag * @devdesc Unable to resolve the VPD * source (PNOR or SEEPROM) */ @@ -1426,8 +1426,8 @@ errlHndl_t IpVpdFacade::fetchData ( uint64_t i_byteAddr, * @moduleid VPD::VPD_IPVPD_FETCH_DATA * @userdata1[0:31] Target HUID * @userdata1[32:63] Requested VPD Source Location - * @userdata2[0:31] CONFIG_<vpd>_READ_FROM_PNOR - * @userdata2[32:63] CONFIG_<vpd>_READ_FROM_HW + * @userdata2[0:31] VPD read PNOR flag + * @userdata2[32:63] VPD read HW flag * @devdesc Unable to resolve the VPD * source (PNOR or SEEPROM) */ @@ -1903,8 +1903,8 @@ errlHndl_t IpVpdFacade::writeKeyword ( const char * i_keywordName, * @moduleid VPD::VPD_IPVPD_WRITE_KEYWORD * @userdata1[0:31] Target HUID * @userdata1[32:63] Requested VPD Destination - * @userdata2[0:31] CONFIG_<vpd>_WRITE_TO_PNOR - * @userdata2[32:63] CONFIG_<vpd>_WRITE_TO_HW + * @userdata2[0:31] VPD write PNOR flag + * @userdata2[32:63] VPD write HW flag * @devdesc Unable to resolve the VPD * destination (PNOR or SEEPROM) */ @@ -2007,3 +2007,24 @@ bool IpVpdFacade::compareKeywords ( const keywordInfo e1, else return false; } + + +// ------------------------------------------------------------------ +// IpVpdFacade::setConfigFlagsHW +// ------------------------------------------------------------------ +void IpVpdFacade::setConfigFlagsHW ( ) +{ + // Only change configs if in PNOR caching mode + if( iv_configInfo.vpdReadPNOR && + iv_configInfo.vpdReadHW ) + { + iv_configInfo.vpdReadPNOR = false; + iv_configInfo.vpdReadHW = true; + } + if( iv_configInfo.vpdWritePNOR && + iv_configInfo.vpdWriteHW ) + { + iv_configInfo.vpdWritePNOR = false; + iv_configInfo.vpdWriteHW = true; + } +} diff --git a/src/usr/vpd/ipvpd.H b/src/usr/vpd/ipvpd.H index e80f19363..bd121dcae 100644 --- a/src/usr/vpd/ipvpd.H +++ b/src/usr/vpd/ipvpd.H @@ -275,6 +275,11 @@ class IpVpdFacade */ errlHndl_t invalidatePnor ( TARGETING::Target * i_target ); + /** + * @brief This function sets the config flags to use HW and not PNOR + */ + void setConfigFlagsHW ( ); + protected: /** diff --git a/src/usr/vpd/rtvpd_load.C b/src/usr/vpd/rtvpd_load.C index dbe31f79f..837d9477b 100644 --- a/src/usr/vpd/rtvpd_load.C +++ b/src/usr/vpd/rtvpd_load.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ +/* [+] 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. */ @@ -101,46 +103,99 @@ errlHndl_t VPD::vpd_load_rt_image(uint64_t & o_vpd_addr) { errlHndl_t err = NULL; - uint64_t vpd_addr = TARGETING::get_top_mem_addr(); - - assert (vpd_addr != 0, - "bld_devtree: Top of memory was 0!"); - - vpd_addr -= VMM_RT_VPD_OFFSET; + do + { + uint64_t vpd_addr = TARGETING::get_top_mem_addr(); - o_vpd_addr = vpd_addr; + assert (vpd_addr != 0, + "bld_devtree: Top of memory was 0!"); - uint8_t * vpd_ptr = reinterpret_cast<uint8_t*>(vpd_addr); + vpd_addr -= VMM_RT_VPD_OFFSET; - void * vptr = mm_block_map(vpd_ptr, VMM_RT_VPD_SIZE); + o_vpd_addr = vpd_addr; - assert(vptr != NULL,"bld_devtree: Could not map VPD memory"); + uint8_t * vpd_ptr = reinterpret_cast<uint8_t*>(vpd_addr); - vpd_ptr = static_cast<uint8_t*>(vptr); + void * vptr = mm_block_map(vpd_ptr, VMM_RT_VPD_SIZE); - err = bld_vpd_image(PNOR::DIMM_JEDEC_VPD, - vpd_ptr, - VMM_DIMM_JEDEC_VPD_SIZE); + assert(vptr != NULL,"bld_devtree: Could not map VPD memory"); - vpd_ptr += VMM_DIMM_JEDEC_VPD_SIZE; + vpd_ptr = static_cast<uint8_t*>(vptr); + err = bld_vpd_image(PNOR::DIMM_JEDEC_VPD, + vpd_ptr, + VMM_DIMM_JEDEC_VPD_SIZE); + if(err) + { + break; + } - if(!err) - { + vpd_ptr += VMM_DIMM_JEDEC_VPD_SIZE; err = bld_vpd_image(PNOR::MODULE_VPD, vpd_ptr, VMM_MODULE_VPD_SIZE); + if(err) + { + break; + } vpd_ptr += VMM_MODULE_VPD_SIZE; - } - - if(!err) - { err = bld_vpd_image(PNOR::CENTAUR_VPD, vpd_ptr, VMM_CENTAUR_VPD_SIZE); - } + if(err) + { + break; + } + + mm_block_unmap(vptr); + + // In manufacturing mode the VPD PNOR cache needs to be cleared + // And the VPD ATTR switch and flags need to be reset + // Note: this code should do nothing when not in PNOR caching mode + TARGETING::Target* l_pTopLevel = NULL; + TARGETING::targetService().getTopLevelTarget(l_pTopLevel); + TARGETING::ATTR_MNFG_FLAGS_type l_mnfgFlags = + l_pTopLevel->getAttr<TARGETING::ATTR_MNFG_FLAGS>(); + + // @todo RTC 118752 Use generic mfg-mode attr when available + if (l_mnfgFlags & TARGETING::MNFG_FLAG_SRC_TERM) + { + // Reset the PNOR config flags to HW - MVPD/CVPD/SPD + // Checks for PNOR caching mode before reset + VPD::setVpdConfigFlagsHW(); + if (err) + { + break; + } + + // Find all the targets with VPD switches + for (TARGETING::TargetIterator target = + TARGETING::targetService().begin(); + target != TARGETING::targetService().end(); + ++target) + { + TARGETING::ATTR_VPD_SWITCHES_type l_switch; + if(target->tryGetAttr<TARGETING::ATTR_VPD_SWITCHES>(l_switch)) + { + if (l_switch.pnorCacheValid) + { + // Invalidate the VPD PNOR for this target + // This also clears the VPD ATTR switch + err = VPD::invalidatePnorCache(*target); + if (err) + { + break; + } + } + } + } + if (err) + { + break; + } + } - mm_block_unmap(vptr); + } while( 0 ); return err; } diff --git a/src/usr/vpd/runtime/makefile b/src/usr/vpd/runtime/makefile index c3c3615b0..7943ffcb0 100644 --- a/src/usr/vpd/runtime/makefile +++ b/src/usr/vpd/runtime/makefile @@ -5,7 +5,9 @@ # # OpenPOWER HostBoot Project # -# COPYRIGHT International Business Machines Corp. 2013,2014 +# Contributors Listed Below - COPYRIGHT 2013,2015 +# [+] 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. @@ -29,11 +31,12 @@ MODULE = vpd_rt include ../vpd.mk #add unique object modules -OBJS += rt_vpd.o +OBJS += rt_vpd.o SUBDIRS += test.d VPATH += .. +CFLAGS += -iquote ../ include $(ROOTPATH)/config.mk diff --git a/src/usr/vpd/runtime/rt_vpd.C b/src/usr/vpd/runtime/rt_vpd.C index d907aee2e..d73b0dc1a 100644 --- a/src/usr/vpd/runtime/rt_vpd.C +++ b/src/usr/vpd/runtime/rt_vpd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -28,9 +28,14 @@ #include <errl/errludtarget.H> #include <vpd/vpdreasoncodes.H> #include <initservice/initserviceif.H> -#include "../vpd.H" +#include <devicefw/driverif.H> +#include <i2c/eepromif.H> #include <runtime/interface.h> #include <targeting/common/util.H> +#include "vpd.H" +#include "mvpd.H" +#include "cvpd.H" +#include "spd.H" // ---------------------------------------------- // Trace definitions @@ -261,29 +266,145 @@ errlHndl_t writePNOR ( uint64_t i_byteAddr, mutex_t * i_mutex ) { errlHndl_t err = NULL; - // Does VPD write ever need to be supported at runtime? - TRACFCOMP(g_trac_vpd, ERR_MRK - "RT writePNOR: VPD write not supported at runtime."); - /*@ - * @errortype - * @reasoncode VPD::VPD_RT_WRITE_NOT_SUPPORTED - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid VPD::VPD_RT_WRITE_PNOR - * @userdata1 target huid - * @userdata2 VPD type - * @devdesc VPD write not supported at runtime - */ - err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - VPD::VPD_RT_WRITE_PNOR, - VPD::VPD_RT_WRITE_NOT_SUPPORTED, - get_huid(i_target), - i_pnorInfo.pnorSection); + int64_t vpdLocation = 0; + uint64_t addr = 0x0; + const char * writeAddr = NULL; - err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, - HWAS::SRCI_PRIORITY_HIGH); + TRACSSCOMP( g_trac_vpd, + ENTER_MRK"RT writePNOR()" ); - err->collectTrace( "VPD", 256); + do + { + if(INITSERVICE::spBaseServicesEnabled()) + { + TRACFCOMP(g_trac_vpd,ERR_MRK"rt_vpd:writePNOR not supported with FSP"); + + /*@ + * @errortype + * @reasoncode VPD::VPD_RT_WRITE_NOT_SUPPORTED + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid VPD::VPD_RT_WRITE_PNOR + * @userdata1 Target + * @userdata2 0 + * @devdesc MBOX send not supported in HBRT + */ + err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_RT_WRITE_PNOR, + VPD::VPD_RT_WRITE_NOT_SUPPORTED, + TARGETING::get_huid(i_target), + 0); + + err->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, + HWAS::SRCI_PRIORITY_HIGH); + + err->collectTrace( "VPD", 256); + + break; + } + + //---------------------------- + // Write memory version of VPD + //---------------------------- + // Fake getPnorAddr gets memory address of VPD + err = getPnorAddr( i_pnorInfo, + io_cachedAddr, + i_mutex ); + if(err) + { + break; + } + + addr = io_cachedAddr; + + err = getVpdLocation( vpdLocation, + i_target); + if(err) + { + break; + } + + // Add Offset for target vpd location + addr += (vpdLocation * i_pnorInfo.segmentSize); + + // Add keyword offset + addr += i_byteAddr; + + TRACUCOMP( g_trac_vpd, + INFO_MRK"Address to write: 0x%08x", + addr ); + + // Write fake VPD in main-store + writeAddr = reinterpret_cast<const char *>( addr ); + memcpy( (void*)(writeAddr), + i_data, + i_numBytes ); + + //-------------------------------- + // Write PNOR cache version of VPD + //-------------------------------- + + // Check if the VPD PNOR cache is loaded for this target + TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches = + i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>(); + if( vpdSwitches.pnorCacheValid ) + { + PNOR::SectionInfo_t info; + writeAddr = NULL; + + // Get SPD PNOR section info from PNOR RP + err = PNOR::getSectionInfo( i_pnorInfo.pnorSection, + info ); + if( err ) + { + break; + } + + addr = info.vaddr; + + // Offset cached address by vpd location multiplier + addr += (vpdLocation * i_pnorInfo.segmentSize); + + // Now offset into that chunk of data by i_byteAddr + addr += i_byteAddr; + + TRACUCOMP( g_trac_vpd, + INFO_MRK"Address to write: 0x%08x", + addr ); + + // Write the data + writeAddr = reinterpret_cast<const char*>( addr ); + memcpy( (void*)(writeAddr), + i_data, + i_numBytes ); + + // Flush the page to make sure it gets to the PNOR + err = PNOR::flush( info.id ); + if( err ) + { + break; + } + } + + //------------------------ + // Write HW version of VPD + //------------------------ + err = DeviceFW::deviceOp( DeviceFW::WRITE, + i_target, + i_data, + i_numBytes, + DEVICE_EEPROM_ADDRESS( + EEPROM::VPD_PRIMARY, + i_byteAddr ) ); + if( err ) + { + break; + } + + } while(0); + + TRACSSCOMP( g_trac_vpd, + EXIT_MRK"RT writePNOR()" ); return err; } @@ -375,7 +496,7 @@ bool resolveVpdSource( TARGETING::Target * i_target, // PNOR needs to be loaded before we can use it TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches = i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>(); - if( vpdSwitches.pnorLoaded ) + if( vpdSwitches.pnorCacheValid ) { o_vpdSource = VPD::PNOR; } diff --git a/src/usr/vpd/spd.C b/src/usr/vpd/spd.C index b4b6a18a9..54837a581 100644 --- a/src/usr/vpd/spd.C +++ b/src/usr/vpd/spd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -87,6 +87,28 @@ uint64_t g_spdPnorAddr = 0x0; // substitute a binary file (dimmspd.dat) into PNOR. const bool g_usePNOR = true; +// Define where to read/write SPD data +#ifdef CONFIG_DJVPD_READ_FROM_PNOR + static bool g_spdReadPNOR = true; +#else + static bool g_spdReadPNOR = false; +#endif +#ifdef CONFIG_DJVPD_READ_FROM_HW + static bool g_spdReadHW = true; +#else + static bool g_spdReadHW = false; +#endif +#ifdef CONFIG_DJVPD_WRITE_TO_PNOR + static bool g_spdWritePNOR = true; +#else + static bool g_spdWritePNOR = false; +#endif +#ifdef CONFIG_DJVPD_WRITE_TO_HW + static bool g_spdWriteHW = true; +#else + static bool g_spdWriteHW = false; +#endif + /** * @brief Compare two values and return whether e2 is greater than @@ -418,21 +440,12 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr, break; } - bool readFromPnorEnabled = false; -#ifdef CONFIG_DJVPD_READ_FROM_PNOR - readFromPnorEnabled = true; -#endif - bool readFromHwEnabled = false; -#ifdef CONFIG_DJVPD_READ_FROM_HW - readFromHwEnabled = true; -#endif - // Determine the SPD source (PNOR/SEEPROM) VPD::vpdCmdTarget vpdSource = VPD::AUTOSELECT; bool configError = false; configError = VPD::resolveVpdSource( i_target, - readFromPnorEnabled, - readFromHwEnabled, + g_spdReadPNOR, + g_spdReadHW, i_location, vpdSource ); @@ -488,8 +501,8 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr, * @moduleid VPD::VPD_SPD_FETCH_DATA * @userdata1[0:31] Target HUID * @userdata1[32:63] Requested VPD Source Location - * @userdata2[0:31] CONFIG_DJVPD_READ_FROM_PNOR - * @userdata2[32:63] CONFIG_DJVPD_READ_FROM_HW + * @userdata2[0:31] SPD read PNOR flag + * @userdata2[32:63] SPD read HW flag * @devdesc Unable to resolve the VPD * source (PNOR or SEEPROM) */ @@ -499,8 +512,8 @@ errlHndl_t spdFetchData ( uint64_t i_byteAddr, VPD::VPD_READ_SOURCE_UNRESOLVED, TWO_UINT32_TO_UINT64( TARGETING::get_huid(i_target), i_location ), - TWO_UINT32_TO_UINT64( readFromHwEnabled, - readFromHwEnabled ), + TWO_UINT32_TO_UINT64( g_spdReadPNOR, + g_spdReadHW ), true /*Add HB SW Callout*/ ); err->collectTrace( "VPD", 256 ); break; @@ -531,44 +544,46 @@ errlHndl_t spdWriteData ( uint64_t i_offset, do { -#ifdef CONFIG_DJVPD_WRITE_TO_HW - if( i_location != VPD::PNOR ) + if( g_spdWriteHW ) { - // Write directly to target's EEPROM. - err = DeviceFW::deviceOp( DeviceFW::WRITE, - i_target, - i_data, - i_numBytes, - DEVICE_EEPROM_ADDRESS( - EEPROM::VPD_PRIMARY, - i_offset ) ); - if( err ) + if( i_location != VPD::PNOR ) { - break; + // Write directly to target's EEPROM. + err = DeviceFW::deviceOp( DeviceFW::WRITE, + i_target, + i_data, + i_numBytes, + DEVICE_EEPROM_ADDRESS( + EEPROM::VPD_PRIMARY, + i_offset ) ); + if( err ) + { + break; + } } } -#endif -#ifdef CONFIG_DJVPD_WRITE_TO_PNOR - if( i_location != VPD::SEEPROM ) + if( g_spdWritePNOR ) { - // Setup info needed to write from PNOR - VPD::pnorInformation info; - info.segmentSize = DIMM_SPD_SECTION_SIZE; - info.maxSegments = DIMM_SPD_MAX_SECTIONS; - info.pnorSection = PNOR::DIMM_JEDEC_VPD; - err = VPD::writePNOR( i_offset, - i_numBytes, - i_data, - i_target, - info, - g_spdPnorAddr, - &g_spdMutex ); - if( err ) + if( i_location != VPD::SEEPROM ) { - break; + // Setup info needed to write to PNOR + VPD::pnorInformation info; + info.segmentSize = DIMM_SPD_SECTION_SIZE; + info.maxSegments = DIMM_SPD_MAX_SECTIONS; + info.pnorSection = PNOR::DIMM_JEDEC_VPD; + err = VPD::writePNOR( i_offset, + i_numBytes, + i_data, + i_target, + info, + g_spdPnorAddr, + &g_spdMutex ); + if( err ) + { + break; + } } } -#endif } while( 0 ); TRACSSCOMP( g_trac_spd, @@ -885,23 +900,24 @@ errlHndl_t spdWriteValue ( VPD::vpdKeyword i_keyword, break; } -#ifndef CONFIG_DJVPD_WRITE_TO_HW - // Send mbox message with new data to Fsp - VPD::VpdWriteMsg_t msgdata; - msgdata.rec_num = i_target->getAttr<TARGETING::ATTR_VPD_REC_NUM>(); - //XXXX=offset relative to whole section - memcpy( msgdata.record, "XXXX", sizeof(msgdata.record) ); - msgdata.offset = entry->offset; - err = VPD::sendMboxWriteMsg( io_buflen, - io_buffer, - i_target, - VPD::VPD_WRITE_DIMM, - msgdata ); - if( err ) + if( !g_spdWriteHW ) { - break; + // Send mbox message with new data to Fsp + VPD::VpdWriteMsg_t msgdata; + msgdata.rec_num = i_target->getAttr<TARGETING::ATTR_VPD_REC_NUM>(); + //XXXX=offset relative to whole section + memcpy( msgdata.record, "XXXX", sizeof(msgdata.record) ); + msgdata.offset = entry->offset; + err = VPD::sendMboxWriteMsg( io_buflen, + io_buffer, + i_target, + VPD::VPD_WRITE_DIMM, + msgdata ); + if( err ) + { + break; + } } -#endif } while( 0 ); TRACSSCOMP( g_trac_spd, @@ -917,11 +933,14 @@ bool spdPresent ( TARGETING::Target * i_target ) { TRACSSCOMP( g_trac_spd, ENTER_MRK"spdPresent()" ); -#if(defined( CONFIG_DJVPD_READ_FROM_HW ) && !defined (__HOSTBOOT_RUNTIME ) ) - return EEPROM::eepromPresence( i_target ); +#ifndef __HOSTBOOT_RUNTIME + if( g_spdReadHW ) + { + return EEPROM::eepromPresence( i_target ); + } +#endif -#else errlHndl_t err = NULL; bool pres = false; @@ -953,7 +972,6 @@ bool spdPresent ( TARGETING::Target * i_target ) } while( 0 ); return pres; -#endif } @@ -2138,13 +2156,13 @@ errlHndl_t loadPnor ( TARGETING::Target * i_target ) // ------------------------------------------------------------------ -// /*invalidatePnorCache*/ +// invalidatePnor // ------------------------------------------------------------------ errlHndl_t invalidatePnor ( TARGETING::Target * i_target ) { errlHndl_t err = NULL; - TRACSSCOMP( g_trac_spd, ENTER_MRK"invalidatePnorCache()" ); + TRACSSCOMP( g_trac_spd, ENTER_MRK"invalidatePnor()" ); // Write SPD section to all Fs uint8_t writeData[DIMM_SPD_SECTION_SIZE]; @@ -2156,14 +2174,36 @@ errlHndl_t invalidatePnor ( TARGETING::Target * i_target ) VPD::PNOR ); if( err ) { - TRACFCOMP( g_trac_spd, ERR_MRK"invalidatePnorCache: " + TRACFCOMP( g_trac_spd, ERR_MRK"invalidatePnor: " "Error invalidating the SPD in PNOR" ); } - TRACSSCOMP( g_trac_spd, EXIT_MRK"invalidatePnorCache()" ); + TRACSSCOMP( g_trac_spd, EXIT_MRK"invalidatePnor()" ); return err; } +// ------------------------------------------------------------------ +// setConfigFlagsHW +// ------------------------------------------------------------------ +void setConfigFlagsHW ( ) +{ + // Only change configs if in PNOR caching mode + // In PNOR only mode we would lose all VPD data + if( g_spdReadPNOR && + g_spdReadHW ) + { + g_spdReadPNOR = false; + g_spdReadHW = true; + } + if( g_spdWritePNOR && + g_spdWriteHW ) + { + g_spdWritePNOR = false; + g_spdWriteHW = true; + } +} + + }; // end namespace SPD diff --git a/src/usr/vpd/spd.H b/src/usr/vpd/spd.H index c7ad2e0cb..8cc66fcf7 100755 --- a/src/usr/vpd/spd.H +++ b/src/usr/vpd/spd.H @@ -452,6 +452,11 @@ errlHndl_t loadPnor ( TARGETING::Target * i_target ); */ errlHndl_t invalidatePnor ( TARGETING::Target * i_target ); +/** + * @brief This function sets the config flags to use HW and not PNOR + */ +void setConfigFlagsHW ( ); + }; // end SPD namespace diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C index b335c81db..921e4e5da 100755 --- a/src/usr/vpd/vpd.C +++ b/src/usr/vpd/vpd.C @@ -396,7 +396,7 @@ bool resolveVpdSource( TARGETING::Target * i_target, // PNOR needs to be loaded before we can use it TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches = i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>(); - if( vpdSwitches.pnorLoaded ) + if( vpdSwitches.pnorCacheValid ) { o_vpdSource = VPD::PNOR; } @@ -560,7 +560,7 @@ errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target ) // Set target attribute switch that says VPD is loaded into PNOR TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches = i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>(); - vpdSwitches.pnorLoaded = 1; + vpdSwitches.pnorCacheValid = 1; i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches ); } while(0); @@ -598,7 +598,7 @@ errlHndl_t invalidatePnorCache ( TARGETING::Target * i_target ) // Clear target attribute switch that says VPD is loaded into PNOR TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches = i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>(); - vpdSwitches.pnorLoaded = 0; + vpdSwitches.pnorCacheValid = 0; i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches ); TRACSSCOMP( g_trac_vpd, EXIT_MRK"invalidatePnorCache()" ); @@ -607,4 +607,15 @@ errlHndl_t invalidatePnorCache ( TARGETING::Target * i_target ) } +// ------------------------------------------------------------------ +// setVpdConfigFlagsHW +// ------------------------------------------------------------------ +void setVpdConfigFlagsHW ( ) +{ + Singleton<MvpdFacade>::instance().setConfigFlagsHW(); + Singleton<CvpdFacade>::instance().setConfigFlagsHW(); + SPD::setConfigFlagsHW(); +} + + }; //end VPD namespace diff --git a/src/usr/vpd/vpd.H b/src/usr/vpd/vpd.H index 96c42c7eb..9c39a7f3d 100644 --- a/src/usr/vpd/vpd.H +++ b/src/usr/vpd/vpd.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -210,8 +210,7 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes, * * @param[out] o_source - The resolved VPD source to be accessed * - * @return errHndl_t - NULL if successful, otherwise a pointer to the - * error log. + * @return bool - True if bad config detected otherwise False */ bool resolveVpdSource( TARGETING::Target * i_target, bool i_rwPnorEnabled, @@ -219,6 +218,7 @@ bool resolveVpdSource( TARGETING::Target * i_target, vpdCmdTarget i_vpdCmdTarget, vpdCmdTarget& o_vpdSource ); + }; //end VPD namespace #endif |