diff options
author | Nick Bofferding <bofferdn@us.ibm.com> | 2014-12-04 14:16:09 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2015-01-22 17:17:39 -0600 |
commit | f8569146fb30162c9bc9d4730d0476f209071fac (patch) | |
tree | 19a495e078dea43580c38cb4c999cb4eac1e909e | |
parent | 1bc13e89d35eacba76589ac3c5158d54ce73b35b (diff) | |
download | talos-hostboot-f8569146fb30162c9bc9d4730d0476f209071fac.tar.gz talos-hostboot-f8569146fb30162c9bc9d4730d0476f209071fac.zip |
Support VDDR enable for Firestone
- Assert GPIOs from MRW info to enable VDDR across FSP-less platforms
- Updated MRW parser to parse GPIO info from MRW
- Updated membuf selection algorithm to choose optimal set of GPIO enables
- Defaulted GPIO_INFO attribute to invalid value
- Updated GPIO device driver to use MRW i2c master path
Change-Id: I0da9e0608af3e8368217c863b2606279637711e5
RTC: 117706
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14710
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r-- | src/usr/gpio/gpiodd.C | 7 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/dram_training/palmetto_vddr.C | 169 | ||||
-rwxr-xr-x | src/usr/targeting/common/genHwsvMrwXml.pl | 119 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/attribute_types_hb.xml | 14 |
4 files changed, 280 insertions, 29 deletions
diff --git a/src/usr/gpio/gpiodd.C b/src/usr/gpio/gpiodd.C index 4dc94650e..5b2c840e7 100644 --- a/src/usr/gpio/gpiodd.C +++ b/src/usr/gpio/gpiodd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -308,10 +308,7 @@ errlHndl_t gpioReadAttributes ( TARGETING::Target * i_target, if( !err ) { - //TODO - RTC 109570 until the the Palmetto attribute file is setup - io_gpioInfo.i2cMasterPath = - i_target->getAttr<TARGETING::ATTR_PHYS_PATH>(); - //io_gpioInfo.i2cMasterPath = gpioData.i2cMasterPath; + io_gpioInfo.i2cMasterPath = gpioData.i2cMasterPath; io_gpioInfo.engine = gpioData.engine; io_gpioInfo.i2cPort = gpioData.port; io_gpioInfo.i2cDeviceAddr = gpioData.devAddr; diff --git a/src/usr/hwpf/hwp/dram_training/palmetto_vddr.C b/src/usr/hwpf/hwp/dram_training/palmetto_vddr.C index 5286d26f6..b456324a4 100644 --- a/src/usr/hwpf/hwp/dram_training/palmetto_vddr.C +++ b/src/usr/hwpf/hwp/dram_training/palmetto_vddr.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014 */ +/* Contributors Listed Below - COPYRIGHT 2014,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -29,6 +29,8 @@ #include "platform_vddr.H" +#include <string.h> + #include <hwpf/hwpf_reasoncodes.H> #include <errl/errlentry.H> #include <errl/errlmanager.H> @@ -48,17 +50,6 @@ using namespace DeviceFW; trace_desc_t* g_trac_vddr = NULL; TRAC_INIT(&g_trac_vddr, "HB_VDDR", KILOBYTE); -/** - * PCA95X GPIO function assignements - */ -enum -{ - // Output GPIO to enable VDDR. (GPIO pin 0) - GPIO_P1V35_EN = 0, - - // No other GPIO pins are implemented on the Palmetto board -}; - // PCA95X internal register addresses enum { @@ -80,14 +71,101 @@ enum // Helper function to call provided function pointer on each functional // centaur Target. -static errlHndl_t for_each_centaur(errlHndl_t (*func)(Target *)) + +//****************************************************************************** +// compareTargetsGpioInfos +//****************************************************************************** + +bool compareTargetsGpioInfos( + TARGETING::TargetHandle_t i_pLhs, + TARGETING::TargetHandle_t i_pRhs) +{ + + TARGETING::ATTR_GPIO_INFO_type lhsGpioInfo = + i_pLhs->getAttr<TARGETING::ATTR_GPIO_INFO>(); + TARGETING::ATTR_GPIO_INFO_type rhsGpioInfo = + i_pRhs->getAttr<TARGETING::ATTR_GPIO_INFO>(); + + // Code logically compares left hand side (lhs) target to right hand side + // (rhs) target with respect to GPIO info and returns true if the left hand + // side is logically before the right hand side. To make the computation, + // compare first GPIO info field for each object. If values are not + // logically equal, return whether the left hand side value was less than + // the right hand side value. Otherwise break the tie by comparing the + // next GPIO field in similar fashion. Continue breaking ties until the + // last field, in which case a tie returns false. + bool lhsLogicallyBeforeRhs = + lhsGpioInfo.i2cMasterPath < rhsGpioInfo.i2cMasterPath; + if(lhsGpioInfo.i2cMasterPath == rhsGpioInfo.i2cMasterPath) + { + lhsLogicallyBeforeRhs = lhsGpioInfo.port < rhsGpioInfo.port; + if(lhsGpioInfo.port == rhsGpioInfo.port) + { + lhsLogicallyBeforeRhs = lhsGpioInfo.engine < rhsGpioInfo.engine; + if(lhsGpioInfo.engine == rhsGpioInfo.engine) + { + lhsLogicallyBeforeRhs + = lhsGpioInfo.devAddr < rhsGpioInfo.devAddr; + if(lhsGpioInfo.devAddr == rhsGpioInfo.devAddr) + { + lhsLogicallyBeforeRhs = + lhsGpioInfo.vddrPin < rhsGpioInfo.vddrPin; + } + } + } + } + + return lhsLogicallyBeforeRhs; +} + +//****************************************************************************** +// areTargetsGpioInfoEqual +//****************************************************************************** + +bool areTargetsGpioInfoEqual( + TARGETING::TargetHandle_t i_pLhs, + TARGETING::TargetHandle_t i_pRhs) +{ + + TARGETING::ATTR_GPIO_INFO_type lhsGpioInfo = + i_pLhs->getAttr<TARGETING::ATTR_GPIO_INFO>(); + TARGETING::ATTR_GPIO_INFO_type rhsGpioInfo = + i_pRhs->getAttr<TARGETING::ATTR_GPIO_INFO>(); + + return( ( lhsGpioInfo.i2cMasterPath + == rhsGpioInfo.i2cMasterPath) + && ( lhsGpioInfo.port + == rhsGpioInfo.port) + && ( lhsGpioInfo.engine + == rhsGpioInfo.engine) + && ( lhsGpioInfo.devAddr + == rhsGpioInfo.devAddr) + && ( lhsGpioInfo.vddrPin + == rhsGpioInfo.vddrPin) ); +} + +static errlHndl_t for_each_vddr_domain_with_functional_memory( + errlHndl_t (*func)(Target *)) { - // Get all Centaur targets + // Get all functional Centaur targets TargetHandleList l_membufTargetList; getAllChips(l_membufTargetList, TYPE_MEMBUF); errlHndl_t l_err = NULL; + // Sort chips in order of GPIO info + std::sort(l_membufTargetList.begin(), l_membufTargetList.end(), + compareTargetsGpioInfos); + + // Prune out targets with non-unique GPIO info + std::vector<TARGETING::TargetHandle_t>::iterator + pInvalidEntries = std::unique( + l_membufTargetList.begin(), + l_membufTargetList.end(), + areTargetsGpioInfoEqual); + l_membufTargetList.erase(pInvalidEntries,l_membufTargetList.end()); + + // Invoke callback for one Centaur per unique VDDR domain for (TargetHandleList::iterator l_membuf_iter = l_membufTargetList.begin(); l_membuf_iter != l_membufTargetList.end(); @@ -196,19 +274,66 @@ static errlHndl_t pca95xGpioWriteBit(TARGETING::Target * i_target, return err; } -static errlHndl_t palmetto_centaur_enable_vddr(Target *centaur) +static errlHndl_t enableVddrViaGpioPinStrategy(Target *centaur) { errlHndl_t l_err = NULL; - // Enable the DIMM power. - l_err = pca95xGpioWriteBit(centaur, GPIO_P1V35_EN, true); + do + { + // Enable the DIMM power. + TARGETING::ATTR_GPIO_INFO_type gpioInfo = + centaur->getAttr<TARGETING::ATTR_GPIO_INFO>(); + + l_err = pca95xGpioWriteBit(centaur, gpioInfo.vddrPin, true); + if(l_err) + { + TRACFCOMP(g_trac_vddr,ERR_MRK " " + "Failed to assert pca95x GPIO for Centaur HUID = 0x%08x " + "and pin %d.", + TARGETING::get_huid(centaur),gpioInfo.vddrPin); + break; + } + + TRACFCOMP(g_trac_vddr,INFO_MRK " " + "Enabled VDDR for Centaur HUID = 0x%08x (asserted pca95x GPIO " + "pin %d).", + TARGETING::get_huid(centaur), + gpioInfo.vddrPin); + + } while(0); return l_err; } -static errlHndl_t palmetto_centaur_disable_vddr(Target *centaur) +static errlHndl_t disableVddrViaGpioPinStrategy(Target *centaur) { - return pca95xGpioWriteBit(centaur, GPIO_P1V35_EN, false); + errlHndl_t l_err = NULL; + + do + { + // Disable the DIMM power. + TARGETING::ATTR_GPIO_INFO_type gpioInfo = + centaur->getAttr<TARGETING::ATTR_GPIO_INFO>(); + + l_err = pca95xGpioWriteBit(centaur,gpioInfo.vddrPin, false); + if(l_err) + { + TRACFCOMP(g_trac_vddr,ERR_MRK " " + "Failed to deassert pca95x GPIO for Centaur HUID = 0x%08x " + "and pin %d.", + TARGETING::get_huid(centaur),gpioInfo.vddrPin); + break; + } + + TRACFCOMP(g_trac_vddr,INFO_MRK " " + "Disabled VDDR for Centaur HUID = 0x%08x (deasserted pca95x GPIO " + "pin %d).", + TARGETING::get_huid(centaur), + gpioInfo.vddrPin); + + } while(0); + + return l_err; } // External interfaces @@ -222,10 +347,12 @@ errlHndl_t platform_enable_vspd() errlHndl_t platform_enable_vddr() { - return for_each_centaur(palmetto_centaur_enable_vddr); + return for_each_vddr_domain_with_functional_memory( + enableVddrViaGpioPinStrategy); } errlHndl_t platform_disable_vddr() { - return for_each_centaur(palmetto_centaur_disable_vddr); + return for_each_vddr_domain_with_functional_memory( + disableVddrViaGpioPinStrategy); } diff --git a/src/usr/targeting/common/genHwsvMrwXml.pl b/src/usr/targeting/common/genHwsvMrwXml.pl index 8bfe40097..b63d4db9a 100755 --- a/src/usr/targeting/common/genHwsvMrwXml.pl +++ b/src/usr/targeting/common/genHwsvMrwXml.pl @@ -396,6 +396,19 @@ use constant MAX_NUM_PHB_PER_PROC => 4; # MAX lane settings value is 32 bytes per phb and is hard coded here use constant MAX_LANE_SETTINGS_PER_PHB => 32; +################################################################################ +# If value is hex, convert to regular number +############################################################################### + +sub unhexify { + my($val) = @_; + if($val =~ m/^0[xX][01234567890A-Fa-f]+$/) + { + $val = hex($val); + } + return $val; +} + # Determine values of proc pcie attributes # Currently # PROC_PCIE_LANE_EQUALIZATION PROC_PCIE_IOP_CONFIG PROC_PCIE_PHB_ACTIVE @@ -1234,6 +1247,67 @@ for my $i ( 0 .. $#SMembuses ) } #------------------------------------------------------------------------------ +# Process VDDR GPIO enables +#------------------------------------------------------------------------------ + +my %vddrEnableHash = (); +my $useGpioToEnableVddr = 0; + +if(!$haveFSPs) +{ + $useGpioToEnableVddr = 1; +} + +if($useGpioToEnableVddr) +{ + my $vddrEnablesFile = open_mrw_file($mrwdir, "${sysname}-vddr.xml"); + my $vddrEnables = parse_xml_file( + $vddrEnablesFile, + forcearray=>['vddr-enable']); + + foreach my $vddrEnable (@{$vddrEnables->{'vddr-enable'}}) + { + # Get dependent Centaur info + my $centaurNode = $vddrEnable->{'centaur-target'}->{node}; + my $centaurPosition = $vddrEnable->{'centaur-target'}->{position}; + + # Get I2C master which drives the GPIO for this Centaur + my $i2cMasterNode = $vddrEnable->{i2c}->{'master-target'}->{node}; + my $i2cMasterPosition + = $vddrEnable->{i2c}->{'master-target'}->{position}; + my $i2cMasterPort = $vddrEnable->{i2c}->{port}; + my $i2cMasterEngine = $vddrEnable->{i2c}->{engine}; + + # Get GPIO expander info. For now these are pca9535 specific + # Targeting requires real i2c address to be shifted left one bit + my $i2cAddress = unhexify( $vddrEnable->{i2c}->{address} ) << 1; + my $i2cAddressHexStr = sprintf("0x%X",$i2cAddress); + my $vddrPort = $vddrEnable->{'io-expander'}->{port}; + my $vddrPortPin = $vddrEnable->{'io-expander'}->{pin}; + my $vddrPin = $vddrPort * 8 + $vddrPortPin; + + # Build foreign keys to the Centaur targets + my $vddrKey = "n" . $centaurNode . "p" . $centaurPosition; + my $i2cMasterKey = "n" . $i2cMasterNode . "p" . $i2cMasterPosition; + my $i2cMasterEntityPath = + "physical:sys-0/node-$i2cMasterNode/membuf-$i2cMasterPosition"; + + # Populate the key => value pairs for a given Centaur + $vddrEnableHash{$vddrKey} = { + 'i2cMasterKey' => $i2cMasterKey, + 'i2cMasterEntityPath' => $i2cMasterEntityPath, + 'i2cMasterNode' => $i2cMasterNode, + 'i2cMasterPosition' => $i2cMasterPosition, + 'i2cMasterPort' => $i2cMasterPort, + 'i2cMasterEngine' => $i2cMasterEngine, + 'i2cAddress' => $i2cAddress, + 'i2cAddressHexStr' => $i2cAddressHexStr, + 'vddrPin' => $vddrPin, + }; + } +} + +#------------------------------------------------------------------------------ # Process the i2c-busses MRW file #------------------------------------------------------------------------------ my $i2c_busses_file = open_mrw_file($mrwdir, "${sysname}-i2c-busses.xml"); @@ -4056,6 +4130,51 @@ sub generate_centaur addI2cBusSpeedArray($sys, $node, $ctaur, "memb"); } + if($useGpioToEnableVddr) + { + my $vddrKey = "n" . $node . "p" . $ctaur; + if(!exists $vddrEnableHash{$vddrKey}) + { + die "FATAL! Cannot find required GPIO info for memory buffer " + . "$vddrKey VDDR enable.\n" + } + elsif(!exists $vddrEnableHash{$vddrEnableHash{$vddrKey}{i2cMasterKey}}) + { + die "FATAL! Must reference real membuf as I2C master for VDDR " + . "enable. Membuf $vddrEnableHash{$vddrKey}{i2cMasterKey} " + . "requested.\n"; + } + else + { + print +"\n <attribute> + <id>GPIO_INFO</id> + <default> + <field> + <id>i2cMasterPath</id> + <value>$vddrEnableHash{$vddrKey}{i2cMasterEntityPath}</value> + </field> + <field> + <id>port</id> + <value>$vddrEnableHash{$vddrKey}{i2cMasterPort}</value> + </field> + <field> + <id>devAddr</id> + <value>$vddrEnableHash{$vddrKey}{i2cAddressHexStr}</value> + </field> + <field> + <id>engine</id> + <value>$vddrEnableHash{$vddrKey}{i2cMasterEngine}</value> + </field> + <field> + <id>vddrPin</id> + <value>$vddrEnableHash{$vddrKey}{vddrPin}</value> + </field> + </default> + </attribute>\n"; + } + } + print "\n</targetInstance>\n"; } diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml index bc16e0854..57fb8e654 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml @@ -279,21 +279,21 @@ <description>Entity path to the chip that contains the I2C master</description> <type>EntityPath</type> - <default>physical:sys-0/node-0/membuf-0</default> + <default>physical:sys-0</default> </field> <field> <name>port</name> <description>Port from the I2C Master device. This is a 6-bit value.</description> <type>uint8_t</type> - <default>1</default> + <default>0</default> </field> <field> <name>devAddr</name> <description>Device address on the I2C bus. This is a 7-bit value, but then shifted 1 bit left.</description> <type>uint8_t</type> - <default>0x40</default> + <default>0</default> </field> <field> <name>engine</name> @@ -302,6 +302,14 @@ <type>uint8_t</type> <default>0</default> </field> + <field> + <name>vddrPin</name> + <description> + Logical GPIO pin number used to enabled/disable VDDR + </description> + <type>uint8_t</type> + <default>0</default> + </field> </complexType> <persistency>non-volatile</persistency> <readable/> |