summaryrefslogtreecommitdiffstats
path: root/openpower/patches/p8dtu-patches/hostboot-p8/0010-Adjust-APSS-gain-and-offset-from-PWS-FRU-information.patch
diff options
context:
space:
mode:
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.patch308
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
+
OpenPOWER on IntegriCloud