diff options
Diffstat (limited to 'openpower/patches/p8dtu-patches/hostboot-p8/0010-Adjust-APSS-gain-and-offset-from-PWS-FRU-information.patch')
-rw-r--r-- | openpower/patches/p8dtu-patches/hostboot-p8/0010-Adjust-APSS-gain-and-offset-from-PWS-FRU-information.patch | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/openpower/patches/p8dtu-patches/hostboot-p8/0010-Adjust-APSS-gain-and-offset-from-PWS-FRU-information.patch b/openpower/patches/p8dtu-patches/hostboot-p8/0010-Adjust-APSS-gain-and-offset-from-PWS-FRU-information.patch new file mode 100644 index 00000000..172d6acc --- /dev/null +++ b/openpower/patches/p8dtu-patches/hostboot-p8/0010-Adjust-APSS-gain-and-offset-from-PWS-FRU-information.patch @@ -0,0 +1,308 @@ +From bdd6ce1bbfe0ee77feefe84662e961fb253c6195 Mon Sep 17 00:00:00 2001 +From: Jim Yuan <jim.yuan@supermicro.com> +Date: Fri, 22 Jul 2016 17:50:57 -0700 +Subject: [PATCH 10/14] Adjust APSS gain and offset from PWS FRU information. + +Signed-off-by: Jim Yuan <jim.yuan@supermicro.com> +--- + src/include/usr/ipmi/ipmiif.H | 4 +- + src/usr/htmgt/htmgt_cfgdata.C | 2 + + src/usr/hwpf/hwp/start_payload/start_payload.C | 212 +++++++++++++++++++++ + .../common/xmltohb/attribute_types_hb.xml | 2 + + 4 files changed, 218 insertions(+), 2 deletions(-) + +diff --git a/src/include/usr/ipmi/ipmiif.H b/src/include/usr/ipmi/ipmiif.H +index 9dfd8ee63..5416ddca0 100644 +--- a/src/include/usr/ipmi/ipmiif.H ++++ b/src/include/usr/ipmi/ipmiif.H +@@ -251,8 +251,8 @@ namespace IPMI + inline const command_t set_sel_time(void) + { return std::make_pair(NETFUN_STORAGE, 0x49); } + +- inline const command_t read_fru_data(void) +- { return std::make_pair(NETFUN_STORAGE, 0x11); } ++ inline const command_t read_fru_data(void) ++ { return std::make_pair(NETFUN_STORAGE, 0x11); } + + inline const command_t write_fru_data(void) + { return std::make_pair(NETFUN_STORAGE, 0x12); } +diff --git a/src/usr/htmgt/htmgt_cfgdata.C b/src/usr/htmgt/htmgt_cfgdata.C +index 19e7b21bf..7c42abdb6 100644 +--- a/src/usr/htmgt/htmgt_cfgdata.C ++++ b/src/usr/htmgt/htmgt_cfgdata.C +@@ -1025,6 +1025,8 @@ void getApssMessageData(uint8_t* o_data, + ATTR_ADC_CHANNEL_OFFSETS_type offset; + sys->tryGetAttr<ATTR_ADC_CHANNEL_OFFSETS>(offset); + ++ TMGT_INF("getApssMessageData: gain is %d, offset is %d", gain[15], offset[15]); //jim ++ + CPPASSERT(sizeof(function) == sizeof(ground)); + CPPASSERT(sizeof(function) == sizeof(gain)); + CPPASSERT(sizeof(function) == sizeof(offset)); +diff --git a/src/usr/hwpf/hwp/start_payload/start_payload.C b/src/usr/hwpf/hwp/start_payload/start_payload.C +index 5d7865a12..ad155f19e 100644 +--- a/src/usr/hwpf/hwp/start_payload/start_payload.C ++++ b/src/usr/hwpf/hwp/start_payload/start_payload.C +@@ -88,6 +88,7 @@ + #include <algorithm> + #include <config.h> + #include <ipmi/ipmiwatchdog.H> ++#include <ipmi/ipmiif.H> //jim + #include <vpd/vpd_if.H> + + #include <hwpf/hwpf_reasoncodes.H> +@@ -95,6 +96,7 @@ + // Uncomment these files as they become available: + // #include "host_start_payload/host_start_payload.H" + ++ + namespace START_PAYLOAD + { + +@@ -277,6 +279,214 @@ errlHndl_t setMaxPstate ( void ) + } + #endif + ++//jim-start ++enum ++{ ++PWS_1600 = 0, ++PWS_1000 = 1, ++PWS_1200 = 2, ++PWS_UNKNOWN = 0xFE, ++}; ++ ++uint8_t getPSUFRUFromIPMICommands(void) ++{ ++ errlHndl_t l_err = NULL; ++ uint8_t* frudata = new uint8_t[120]; ++ size_t len = 4; ++ uint8_t fru_header_version = 0; ++ uint8_t j = 0, loop_break = 0, read_offset = 0; ++ ++ //create request data buffer ++ uint8_t* data = new uint8_t[len]; ++ ++ IPMI::completion_code cc = IPMI::CC_UNKBAD; ++ ++ data[0] = 60; //try to read from PWS1. 60-PWS1, 61-PWS2 ++ data[1] = 0x0; ++ data[2] = 0x0; ++ data[3] = 8; ++ l_err = IPMI::sendrecv(IPMI::read_fru_data(), cc, len, data); ++ ++ for (uint8_t i = 0; i <= 8; i++ ) ++ fru_header_version = data[1] & 0xF; //normal should be 0x01. ++ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "fru header version is %x", fru_header_version); ++ delete[] data; ++ ++ if((l_err == NULL) && (cc == IPMI::CC_OK) && (fru_header_version == 1)) ++ { ++ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "could get FRU from PWS1"); ++ ++ while ((l_err == NULL) && (loop_break == 0) && (read_offset < 100)) ++ { ++ //create request data buffer ++ len = 4; //must set len every time ++ uint8_t* data = new uint8_t[len]; ++ ++ IPMI::completion_code cc = IPMI::CC_UNKBAD; ++ ++ data[0] = 60; //read from PWS1 ++ data[1] = read_offset; ++ data[2] = 0x0; ++ data[3] = 8; ++ l_err = IPMI::sendrecv(IPMI::read_fru_data(), cc, len, data); ++ ++ if (cc != IPMI::CC_OK) loop_break = 1; ++ ++ read_offset += 8; ++ for (uint8_t i = 1; i <= 8; i++ ) ++ { ++ frudata[j] = data[i]; ++ j++; ++ } ++ delete[] data; ++ } ++ ++ ++ } ++ else ++ { ++ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "could get FRU from PWS2"); ++ ++ while ((l_err == NULL) && (loop_break == 0) && (read_offset < 100)) ++ { ++ //create request data buffer ++ len = 4;//must set len every time ++ uint8_t* data = new uint8_t[len]; ++ ++ IPMI::completion_code cc = IPMI::CC_UNKBAD; ++ ++ data[0] = 61; //read from PWS2 ++ data[1] = read_offset; ++ data[2] = 0x0; ++ data[3] = 8; ++ l_err = IPMI::sendrecv(IPMI::read_fru_data(), cc, len, data); ++ ++ if (cc != IPMI::CC_OK) loop_break = 1; ++ ++ read_offset += 8; ++ for (uint8_t i = 1; i <= 8; i++ ) ++ { ++ frudata[j] = data[i]; ++ j++; ++ } ++ delete[] data; ++ } ++ ++ } ++ ++ uint8_t product_info_offset, manufacture_name_offset, manufacture_name_length, product_name_offset, product_name_length; ++ uint8_t product_partnumber_offset, product_partnumber_length; ++ uint8_t fru_offset, powerSupplyFru = PWS_UNKNOWN; ++ uint8_t pws1600[] = {'P','W','S','-','1','K','6','2','A','-','1','R'}; ++ uint8_t pws1000[] = {'P','W','S','-','1','K','0','2','A','-','1','R'}; ++ uint8_t pws1200[] = {'P','W','S','-','1','K','2','2','A','-','1','R'}; ++ ++ //code to calculate product part number size and offset. should use structure. refer to FRU spec. ++ product_info_offset = frudata[4] * 8; ++ manufacture_name_offset = product_info_offset + 3; ++ manufacture_name_length = frudata[manufacture_name_offset] & 0x3F; ++ product_name_offset = manufacture_name_offset + manufacture_name_length + 1; ++ product_name_length = frudata[product_name_offset] & 0x3F; ++ product_partnumber_offset = product_name_offset + product_name_length + 1; ++ product_partnumber_length = frudata[product_partnumber_offset] & 0x3F; ++ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "product_partnumber_length is %x", product_partnumber_length); ++ fru_offset = product_partnumber_offset + 1; ++ ++ if (product_partnumber_length == 12) ++ { ++ for (uint8_t i = 0; pws1600[i] == frudata[fru_offset + i] ; i ++) ++ if (i == 11) ++ powerSupplyFru = PWS_1600; ++ ++ for (uint8_t i = 0; pws1000[i] == frudata[fru_offset + i] ; i ++) ++ if (i == 11) ++ powerSupplyFru = PWS_1000; ++ ++ for (uint8_t i = 0; pws1200[i] == frudata[fru_offset + i] ; i ++) ++ if (i == 11) ++ powerSupplyFru = PWS_1200; ++ } ++ else ++ powerSupplyFru = PWS_UNKNOWN; ++ ++ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "powerSupplyFru is %x", powerSupplyFru); ++ ++ return powerSupplyFru; ++ ++} ++//find apss channel number from XML. ++enum ++{ ++V12_SENSE = 0, ++PROC0_POWER = 1, ++PROC1_POWER = 2, ++PCIE_PROC0_POWER = 5, ++PCIE_PROC1_POWER = 6, ++TOTAL_SYSTEM_POWER = 15, ++}; ++ ++void setAPSSGainOffsetFromPWSInfo(void) ++{ ++ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "before load OCC"); ++ ++ //Get Gain/Offset ATTR ++ TARGETING::Target* sys = NULL; ++ targetService().getTopLevelTarget(sys); ++ ++ ATTR_ADC_CHANNEL_GAINS_type gain; ++ sys->tryGetAttr<ATTR_ADC_CHANNEL_GAINS>(gain); ++ ++ ATTR_ADC_CHANNEL_OFFSETS_type offset; ++ sys->tryGetAttr<ATTR_ADC_CHANNEL_OFFSETS>(offset); ++ ++ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "gain is %d, offset is %d", gain[15], offset[15]); ++ ++ //Note that the function/ APSS channel ids can be indirect. I've hardcoded here, you will need to look at the XML to find the channel/function number that matches ++ //const uint8_t SYS_CHANNEL = 15; //APSS Channel 15 is sys power, ie the gain/offset we need to tweak ++ ++ //Get power supply data from BMC ++ uint8_t powerSupplyFru = getPSUFRUFromIPMICommands(); ++ ++ switch(powerSupplyFru) ++ { ++ case PWS_1600: //PWS-1K62A-1R (1600W): ++ gain[TOTAL_SYSTEM_POWER] = 67800; ++ offset[TOTAL_SYSTEM_POWER] = 0; ++ break; ++ ++ case PWS_1000: //PWS-1K02A-1R (1000W): ++ gain[TOTAL_SYSTEM_POWER] = 41500; ++ offset[TOTAL_SYSTEM_POWER] = 0; ++ break; ++ ++ case PWS_1200: //PWS-1K22A-1R (1200W): ++ gain[TOTAL_SYSTEM_POWER] = 50000; ++ offset[TOTAL_SYSTEM_POWER] = 0; ++ break; ++ ++ default: ++ //Do nothing, leave defaults ++ //Gen error for user attention? ++ break; ++ } ++ ++ //Now write the attributes back so they get picked up by OCC code ++ if (!sys->trySetAttr<ATTR_ADC_CHANNEL_GAINS>(gain)) ++ { ++ //unlikely, crash ++ //Emit failing trace/console data ++ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "set gain failed"); ++ assert(0); ++ } ++ ++ if (!sys->trySetAttr<ATTR_ADC_CHANNEL_OFFSETS>(offset)) ++ { ++ //unlikely, crash ++ //Emit failing trace/console data ++ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "set offset failed"); ++ assert(0); ++ } ++} + // + // Wrapper function to call host_runtime_setup + // +@@ -318,6 +528,8 @@ void* call_host_runtime_setup( void *io_pArgs ) + break; + } + ++ setAPSSGainOffsetFromPWSInfo(); //jim add code before activate OCC. START_OCC_DURING_BOOT is defined in config. ++ + bool l_activateOCC = is_avp_load(); + + #ifdef CONFIG_START_OCC_DURING_BOOT +diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml +index c4eb6603d..64a0c9bae 100644 +--- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml ++++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml +@@ -747,6 +747,7 @@ + </simpleType> + <persistency>non-volatile</persistency> + <readable/> ++ <writeable/> + </attribute> + + <attribute> +@@ -758,6 +759,7 @@ + </simpleType> + <persistency>non-volatile</persistency> + <readable/> ++ <writeable/> + </attribute> + + <attribute> +-- +2.16.2.windows.1 + |