Home | History | Annotate | Download | only in PlatformInit
      1 /** @file
      2 This PEIM initialize platform for MRC, following action is performed,
      3 1. Initizluize GMCH
      4 2. Detect boot mode
      5 3. Detect video adapter to determine whether we need pre allocated memory
      6 4. Calls MRC to initialize memory and install a PPI notify to do post memory initialization.
      7 This file contains the main entrypoint of the PEIM.
      8 
      9 Copyright (c) 2013 - 2016 Intel Corporation.
     10 
     11 This program and the accompanying materials
     12 are licensed and made available under the terms and conditions of the BSD License
     13 which accompanies this distribution.  The full text of the license may be found at
     14 http://opensource.org/licenses/bsd-license.php
     15 
     16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     18 
     19 **/
     20 
     21 
     22 #include "CommonHeader.h"
     23 #include "PlatformEarlyInit.h"
     24 #include "PeiFvSecurity.h"
     25 
     26 EFI_STATUS
     27 EFIAPI
     28 EndOfPeiSignalPpiNotifyCallback (
     29   IN EFI_PEI_SERVICES           **PeiServices,
     30   IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
     31   IN VOID                       *Ppi
     32   );
     33 
     34 //
     35 // Function prototypes to routines implemented in other source modules
     36 // within this component.
     37 //
     38 
     39 EFI_STATUS
     40 EFIAPI
     41 PlatformErratasPostMrc (
     42   VOID
     43   );
     44 
     45 //
     46 // The global indicator, the FvFileLoader callback will modify it to TRUE after loading PEIM into memory
     47 //
     48 BOOLEAN ImageInMemory = FALSE;
     49 
     50 BOARD_LEGACY_GPIO_CONFIG      mBoardLegacyGpioConfigTable[]  = { PLATFORM_LEGACY_GPIO_TABLE_DEFINITION };
     51 UINTN                         mBoardLegacyGpioConfigTableLen = (sizeof(mBoardLegacyGpioConfigTable) / sizeof(BOARD_LEGACY_GPIO_CONFIG));
     52 BOARD_GPIO_CONTROLLER_CONFIG  mBoardGpioControllerConfigTable[]  = { PLATFORM_GPIO_CONTROLLER_CONFIG_DEFINITION };
     53 UINTN                         mBoardGpioControllerConfigTableLen = (sizeof(mBoardGpioControllerConfigTable) / sizeof(BOARD_GPIO_CONTROLLER_CONFIG));
     54 UINT8                         ChipsetDefaultMac [6] = {0xff,0xff,0xff,0xff,0xff,0xff};
     55 
     56 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[1] = {
     57   {
     58     (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     59     &gEfiPeiMasterBootModePpiGuid,
     60     NULL
     61   }
     62 };
     63 
     64 EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = {
     65   {
     66     (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     67     &gEfiPeiMemoryDiscoveredPpiGuid,
     68     MemoryDiscoveredPpiNotifyCallback
     69   }
     70 };
     71 
     72 EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiSignalPpiNotifyList[1] = {
     73   {
     74     (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     75     &gEfiEndOfPeiSignalPpiGuid,
     76     EndOfPeiSignalPpiNotifyCallback
     77   }
     78 };
     79 
     80 EFI_PEI_STALL_PPI mStallPpi = {
     81   PEI_STALL_RESOLUTION,
     82   Stall
     83 };
     84 
     85 EFI_PEI_PPI_DESCRIPTOR mPpiStall[1] = {
     86   {
     87     (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     88     &gEfiPeiStallPpiGuid,
     89     &mStallPpi
     90   }
     91 };
     92 
     93 /**
     94   Set Mac address on chipset ethernet device.
     95 
     96   @param  Bus      PCI Bus number of chipset ethernet device.
     97   @param  Device   Device number of chipset ethernet device.
     98   @param  Func     PCI Function number of chipset ethernet device.
     99   @param  MacAddr  MAC Address to set.
    100 
    101 **/
    102 VOID
    103 EFIAPI
    104 SetLanControllerMacAddr (
    105   IN CONST UINT8                          Bus,
    106   IN CONST UINT8                          Device,
    107   IN CONST UINT8                          Func,
    108   IN CONST UINT8                          *MacAddr,
    109   IN CONST UINT32                         Bar0
    110   )
    111 {
    112   UINT32                            Data32;
    113   UINT16                            PciVid;
    114   UINT16                            PciDid;
    115   UINT32                            Addr;
    116   UINT32                            MacVer;
    117   volatile UINT8                    *Wrote;
    118   UINT32                            DevPcieAddr;
    119   UINT16                            SaveCmdReg;
    120   UINT32                            SaveBarReg;
    121 
    122   DevPcieAddr = PCI_LIB_ADDRESS (
    123                   Bus,
    124                   Device,
    125                   Func,
    126                   0
    127                   );
    128 
    129   //
    130   // Do nothing if not a supported device.
    131   //
    132   PciVid = PciRead16 (DevPcieAddr + PCI_VENDOR_ID_OFFSET);
    133   PciDid = PciRead16 (DevPcieAddr + PCI_DEVICE_ID_OFFSET);
    134   if((PciVid != V_IOH_MAC_VENDOR_ID) || (PciDid != V_IOH_MAC_DEVICE_ID)) {
    135     return;
    136   }
    137 
    138   //
    139   // Save current settings for PCI CMD/BAR registers
    140   //
    141   SaveCmdReg = PciRead16 (DevPcieAddr + PCI_COMMAND_OFFSET);
    142   SaveBarReg = PciRead32 (DevPcieAddr + R_IOH_MAC_MEMBAR);
    143 
    144   //
    145   // Use predefined temporary memory resource
    146   //
    147   PciWrite32 ( DevPcieAddr + R_IOH_MAC_MEMBAR, Bar0);
    148   PciWrite8 ( DevPcieAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
    149 
    150   Addr =  Bar0 + R_IOH_MAC_GMAC_REG_8;
    151   MacVer = *((volatile UINT32 *) (UINTN)(Addr));
    152 
    153   DEBUG ((EFI_D_INFO, "Ioh MAC [B:%d, D:%d, F:%d] VER:%04x ADDR:",
    154     (UINTN) Bus,
    155     (UINTN) Device,
    156     (UINTN) Func,
    157     (UINTN) MacVer
    158     ));
    159 
    160   //
    161   // Set MAC Address0 Low Register (GMAC_REG_17) ADDRLO bits.
    162   //
    163   Addr =  Bar0 + R_IOH_MAC_GMAC_REG_17;
    164   Data32 = *((UINT32 *) (UINTN)(&MacAddr[0]));
    165   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
    166   Wrote = (volatile UINT8 *) (UINTN)(Addr);
    167   DEBUG ((EFI_D_INFO, "%02x-%02x-%02x-%02x-",
    168     (UINTN) Wrote[0],
    169     (UINTN) Wrote[1],
    170     (UINTN) Wrote[2],
    171     (UINTN) Wrote[3]
    172     ));
    173 
    174   //
    175   // Set MAC Address0 High Register (GMAC_REG_16) ADDRHI bits
    176   // and Address Enable (AE) bit.
    177   //
    178   Addr =  Bar0 + R_IOH_MAC_GMAC_REG_16;
    179   Data32 =
    180     ((UINT32) MacAddr[4]) |
    181     (((UINT32)MacAddr[5]) << 8) |
    182     B_IOH_MAC_AE;
    183   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
    184   Wrote = (volatile UINT8 *) (UINTN)(Addr);
    185 
    186   DEBUG ((EFI_D_INFO, "%02x-%02x\n", (UINTN) Wrote[0], (UINTN) Wrote[1]));
    187 
    188   //
    189   // Restore settings for PCI CMD/BAR registers
    190   //
    191   PciWrite32 ((DevPcieAddr + R_IOH_MAC_MEMBAR), SaveBarReg);
    192   PciWrite16 (DevPcieAddr + PCI_COMMAND_OFFSET, SaveCmdReg);
    193 }
    194 
    195 /**
    196   Initialize state of I2C GPIO expanders.
    197 
    198   @param  PlatformType  Platform type for GPIO expander init.
    199 
    200 **/
    201 EFI_STATUS
    202 EarlyPlatformConfigGpioExpanders (
    203   IN CONST EFI_PLATFORM_TYPE              PlatformType,
    204   EFI_BOOT_MODE                           BootMode
    205   )
    206 {
    207   EFI_STATUS              Status;
    208   EFI_I2C_DEVICE_ADDRESS  I2CSlaveAddress;
    209   UINTN                   Length;
    210   UINTN                   ReadLength;
    211   UINT8                   Buffer[2];
    212 
    213   //
    214   // Configure GPIO expanders for Galileo Gen 2
    215   // Route I2C pins to Arduino header
    216   // Set all GPIO expander pins connected to the Reset Button as inputs
    217   //
    218   if (PlatformType == GalileoGen2) {
    219     //
    220     // Configure AMUX1_IN (EXP2.P1_4) as an output
    221     //
    222     PlatformPcal9555GpioSetDir (
    223       GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2.
    224       12,                                   // P1-4.
    225       FALSE                                 // Configure as output
    226       );
    227 
    228     //
    229     // Set AMUX1_IN(EXP2.P1_4) low to route I2C to Arduino Shield connector
    230     //
    231     PlatformPcal9555GpioSetLevel (
    232       GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2.
    233       12,                                   // P1-4.
    234       FALSE                                 // Set pin low
    235       );
    236 
    237     //
    238     // Configure Reset Button(EXP1.P1_7) as an input
    239     //
    240     PlatformPcal9555GpioSetDir (
    241       GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR,  // IO Expander 1.
    242       15,                                   // P1-7.
    243       TRUE
    244       );
    245 
    246     //
    247     // Disable pullup on Reset Button(EXP1.P1_7)
    248     //
    249     PlatformPcal9555GpioDisablePull (
    250       GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR,  // IO Expander 1.
    251       15                                    // P1-7.
    252       );
    253 
    254     //
    255     // Configure Reset Button(EXP2.P1_7) as an input
    256     //
    257     PlatformPcal9555GpioSetDir (
    258       GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2.
    259       15,                                   // P1-7.
    260       TRUE
    261       );
    262 
    263     //
    264     // Disable pullup on Reset Button(EXP2.P1_7)
    265     //
    266     PlatformPcal9555GpioDisablePull (
    267       GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2.
    268       15                                    // P1-7.
    269       );
    270 
    271     if (BootMode != BOOT_IN_RECOVERY_MODE) {
    272       //
    273       // Read state of Reset Button - EXP2.P1_7
    274       // This GPIO is pulled high when the button is not pressed
    275       // This GPIO reads low when button is pressed
    276       //
    277       if (!PlatformPcal9555GpioGetState (
    278              GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR,  // IO Expander 2
    279              15                                    // P1-7
    280              )) {
    281         DEBUG ((EFI_D_INFO, "  Force Recovery mode and reset\n"));
    282 
    283         //
    284         // Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset
    285         //
    286         QNCAltPortWrite (
    287           QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
    288           QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,
    289           QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW) | B_CFG_STICKY_RW_FORCE_RECOVERY
    290           );
    291         ResetWarm();
    292       }
    293     }
    294   }
    295 
    296   //
    297   // Configure GPIO expanders for Galileo Gen 2
    298   // Set all GPIO expander pins connected to the Reset Button as inputs
    299   // Route I2C pins to Arduino header
    300   //
    301   if (PlatformType == Galileo) {
    302     //
    303     // Detect the I2C Slave Address of the GPIO Expander
    304     //
    305     if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {
    306       I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2HI_7BIT_SLAVE_ADDR;
    307     } else {
    308       I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2LO_7BIT_SLAVE_ADDR;
    309     }
    310     DEBUG ((EFI_D_INFO, "Galileo GPIO Expender Slave Address = %02x\n", I2CSlaveAddress.I2CDeviceAddress));
    311 
    312     //
    313     // Set I2C_MUX (GPORT1_BIT5) low to route I2C to Arduino Shield connector
    314     //
    315 
    316     //
    317     // Select GPIO Expander GPORT1
    318     //
    319     Length = 2;
    320     Buffer[0] = 0x18; //sub-address
    321     Buffer[1] = 0x01; //data
    322     Status = I2cWriteMultipleByte (
    323       I2CSlaveAddress,
    324       EfiI2CSevenBitAddrMode,
    325       &Length,
    326       &Buffer
    327       );
    328     ASSERT_EFI_ERROR (Status);
    329 
    330     //
    331     // Read "Pin Direction" of GPIO Expander GPORT1
    332     //
    333     Length = 1;
    334     ReadLength = 1;
    335     Buffer[1] = 0x1C;
    336     Status = I2cReadMultipleByte (
    337       I2CSlaveAddress,
    338       EfiI2CSevenBitAddrMode,
    339       &Length,
    340       &ReadLength,
    341       &Buffer[1]
    342       );
    343     ASSERT_EFI_ERROR (Status);
    344 
    345     //
    346     // Configure GPIO Expander GPORT1_BIT5 as an output
    347     //
    348     Length = 2;
    349     Buffer[0] = 0x1C; //sub-address
    350     Buffer[1] = (UINT8)(Buffer[1] & (~BIT5)); //data
    351 
    352     Status = I2cWriteMultipleByte (
    353       I2CSlaveAddress,
    354       EfiI2CSevenBitAddrMode,
    355       &Length,
    356       &Buffer
    357       );
    358     ASSERT_EFI_ERROR (Status);
    359 
    360     //
    361     // Set GPIO Expander GPORT1_BIT5 low
    362     //
    363     Length = 2;
    364     Buffer[0] = 0x09; //sub-address
    365     Buffer[1] = (UINT8)(~BIT5); //data
    366 
    367     Status = I2cWriteMultipleByte (
    368       I2CSlaveAddress,
    369       EfiI2CSevenBitAddrMode,
    370       &Length,
    371       &Buffer
    372       );
    373     ASSERT_EFI_ERROR (Status);
    374 
    375     //
    376     // Configure RESET_N_SHLD (GPORT5_BIT0) and SW_RESET_N_SHLD (GPORT5_BIT1) as inputs
    377     //
    378 
    379     //
    380     // Select GPIO Expander GPORT5
    381     //
    382     Length = 2;
    383     Buffer[0] = 0x18;
    384     Buffer[1] = 0x05;
    385     Status = I2cWriteMultipleByte (
    386       I2CSlaveAddress,
    387       EfiI2CSevenBitAddrMode,
    388       &Length,
    389       &Buffer
    390       );
    391     ASSERT_EFI_ERROR (Status);
    392 
    393     //
    394     // Read "Pin Direction" of GPIO Expander GPORT5
    395     //
    396     Length = 1;
    397     ReadLength = 1;
    398     Buffer[1] = 0x1C;
    399     Status = I2cReadMultipleByte (
    400       I2CSlaveAddress,
    401       EfiI2CSevenBitAddrMode,
    402       &Length,
    403       &ReadLength,
    404       &Buffer[1]
    405       );
    406     ASSERT_EFI_ERROR (Status);
    407 
    408     //
    409     // Configure GPIO Expander GPORT5_BIT0 and GPORT5_BIT1 as inputs
    410     //
    411     Length = 2;
    412     Buffer[0] = 0x1C;
    413     Buffer[1] = Buffer[1] | BIT0 | BIT1;
    414     Status = I2cWriteMultipleByte (
    415       I2CSlaveAddress,
    416       EfiI2CSevenBitAddrMode,
    417       &Length,
    418       &Buffer
    419       );
    420     ASSERT_EFI_ERROR (Status);
    421 
    422     if (BootMode != BOOT_IN_RECOVERY_MODE) {
    423       //
    424       // Read state of RESET_N_SHLD (GPORT5_BIT0)
    425       //
    426       Buffer[1] = 5;
    427       Length = 1;
    428       ReadLength = 1;
    429       Status = I2cReadMultipleByte (
    430                  I2CSlaveAddress,
    431                  EfiI2CSevenBitAddrMode,
    432                  &Length,
    433                  &ReadLength,
    434                  &Buffer[1]
    435                  );
    436       ASSERT_EFI_ERROR (Status);
    437 
    438       //
    439       // Return the state of GPORT5_BIT0
    440       //
    441       if ((Buffer[1] & BIT0) == 0) {
    442         DEBUG ((EFI_D_INFO, "  Force Recovery mode and reset\n"));
    443 
    444         //
    445         // Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset
    446         //
    447         QNCAltPortWrite (
    448           QUARK_SCSS_SOC_UNIT_SB_PORT_ID,
    449           QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,
    450           QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW) | B_CFG_STICKY_RW_FORCE_RECOVERY
    451           );
    452         ResetWarm();
    453       }
    454     }
    455   }
    456 
    457   return EFI_SUCCESS;
    458 }
    459 
    460 /**
    461   This is the entrypoint of PEIM
    462 
    463   @param  FileHandle  Handle of the file being invoked.
    464   @param  PeiServices Describes the list of possible PEI Services.
    465 
    466   @retval EFI_SUCCESS if it completed successfully.
    467 **/
    468 EFI_STATUS
    469 EFIAPI
    470 PeiInitPlatform (
    471   IN       EFI_PEI_FILE_HANDLE  FileHandle,
    472   IN CONST EFI_PEI_SERVICES     **PeiServices
    473   )
    474 {
    475   EFI_STATUS                              Status;
    476   EFI_BOOT_MODE                           BootMode;
    477   EFI_PEI_STALL_PPI                       *StallPpi;
    478   EFI_PEI_PPI_DESCRIPTOR                  *StallPeiPpiDescriptor;
    479   EFI_FV_FILE_INFO                        FileInfo;
    480   EFI_PLATFORM_TYPE                       PlatformType;
    481 
    482   PlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);
    483 
    484   //
    485   // Initialize Firmware Volume security.
    486   // This must be done before any firmware volume accesses (excl. BFV)
    487   //
    488   Status = PeiInitializeFvSecurity();
    489   ASSERT_EFI_ERROR (Status);
    490 
    491   //
    492   // Do any early platform specific initialization.
    493   //
    494   EarlyPlatformInit ();
    495 
    496   //
    497   // This is a second path on entry, in recovery boot path the Stall PPI need to be memory-based
    498   // to improve recovery performance.
    499   //
    500   Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
    501   ASSERT_EFI_ERROR (Status);
    502   //
    503   // The follow conditional check only works for memory-mapped FFS,
    504   // so we ASSERT that the file is really a MM FFS.
    505   //
    506   ASSERT (FileInfo.Buffer != NULL);
    507   if (!(((UINTN) FileInfo.Buffer <= (UINTN) PeiInitPlatform) &&
    508         ((UINTN) PeiInitPlatform <= (UINTN) FileInfo.Buffer + FileInfo.BufferSize))) {
    509     //
    510     // Now that module in memory, update the
    511     // PPI that describes the Stall to other modules
    512     //
    513     Status = PeiServicesLocatePpi (
    514                &gEfiPeiStallPpiGuid,
    515                0,
    516                &StallPeiPpiDescriptor,
    517                (VOID **) &StallPpi
    518                );
    519 
    520     if (!EFI_ERROR (Status)) {
    521 
    522       Status = PeiServicesReInstallPpi (
    523                  StallPeiPpiDescriptor,
    524                  &mPpiStall[0]
    525                  );
    526     } else {
    527 
    528       Status = PeiServicesInstallPpi (&mPpiStall[0]);
    529     }
    530     return Status;
    531   }
    532 
    533   //
    534   // Initialize System Phys
    535   //
    536 
    537   // Program USB Phy
    538   InitializeUSBPhy();
    539 
    540   //
    541   // Do platform specific logic to create a boot mode
    542   //
    543   Status = UpdateBootMode ((EFI_PEI_SERVICES**)PeiServices, &BootMode);
    544   ASSERT_EFI_ERROR (Status);
    545 
    546   //
    547   // Signal possible dependent modules that there has been a
    548   // final boot mode determination
    549   //
    550   if (!EFI_ERROR(Status)) {
    551     Status = PeiServicesInstallPpi (&mPpiBootMode[0]);
    552     ASSERT_EFI_ERROR (Status);
    553   }
    554 
    555   if (BootMode != BOOT_ON_S3_RESUME) {
    556     QNCClearSmiAndWake ();
    557   }
    558 
    559   DEBUG ((EFI_D_INFO, "MRC Entry\n"));
    560   MemoryInit ((EFI_PEI_SERVICES**)PeiServices);
    561 
    562   //
    563   // Do Early PCIe init.
    564   //
    565   DEBUG ((EFI_D_INFO, "Early PCIe controller initialization\n"));
    566   PlatformPciExpressEarlyInit (PlatformType);
    567 
    568 
    569   DEBUG ((EFI_D_INFO, "Platform Erratas After MRC\n"));
    570   PlatformErratasPostMrc ();
    571 
    572   //
    573   //
    574   //
    575   DEBUG ((EFI_D_INFO, "EarlyPlatformConfigGpioExpanders ()\n"));
    576   EarlyPlatformConfigGpioExpanders (PlatformType, BootMode);
    577 
    578   //
    579   // Now that all of the pre-permanent memory activities have
    580   // been taken care of, post a call-back for the permanent-memory
    581   // resident services, such as HOB construction.
    582   // PEI Core will switch stack after this PEIM exit.  After that the MTRR
    583   // can be set.
    584   //
    585   Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList[0]);
    586   ASSERT_EFI_ERROR (Status);
    587 /*
    588 
    589   if (BootMode != BOOT_ON_S3_RESUME) {
    590     Status = PeiServicesNotifyPpi (mEndOfPeiSignalPpiNotifyList);
    591     ASSERT_EFI_ERROR (Status);
    592   }
    593 */
    594   if (BootMode == BOOT_IN_RECOVERY_MODE) {
    595     PeiServicesRegisterForShadow (FileHandle);
    596   }
    597 
    598   return Status;
    599 }
    600 
    601 EFI_STATUS
    602 EFIAPI
    603 EndOfPeiSignalPpiNotifyCallback (
    604   IN EFI_PEI_SERVICES           **PeiServices,
    605   IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
    606   IN VOID                       *Ppi
    607   )
    608 {
    609   EFI_STATUS                            Status;
    610 
    611   DEBUG ((EFI_D_INFO, "End of PEI Signal Callback\n"));
    612 
    613     //
    614   // Restore the flash region to be UC
    615   // for both normal boot as we build a Resource Hob to
    616   // describe this region as UC to DXE core.
    617   //
    618   WriteBackInvalidateDataCacheRange (
    619     (VOID *) (UINTN) PcdGet32 (PcdFlashAreaBaseAddress),
    620     PcdGet32 (PcdFlashAreaSize)
    621   );
    622 
    623   Status = MtrrSetMemoryAttribute (PcdGet32 (PcdFlashAreaBaseAddress), PcdGet32 (PcdFlashAreaSize), CacheUncacheable);
    624   ASSERT_EFI_ERROR (Status);
    625 
    626   return EFI_SUCCESS;
    627 }
    628 
    629 /**
    630   This function will initialize USB Phy registers associated with QuarkSouthCluster.
    631 
    632   @param  VOID                  No Argument
    633 
    634   @retval EFI_SUCCESS           All registers have been initialized
    635 **/
    636 VOID
    637 EFIAPI
    638 InitializeUSBPhy (
    639     VOID
    640    )
    641 {
    642     UINT32 RegData32;
    643 
    644     /** In order to configure the PHY to use clk120 (ickusbcoreclk) as PLL reference clock
    645      *  and Port2 as a USB device port, the following sequence must be followed
    646      *
    647      **/
    648 
    649     // Sideband register write to USB AFE (Phy)
    650     RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_GLOBAL_PORT);
    651     RegData32 &= ~(BIT1);
    652     //
    653     // Sighting #4930631 PDNRESCFG [8:7] of USB2_GLOBAL_PORT = 11b.
    654     // For port 0 & 1 as host and port 2 as device.
    655     //
    656     RegData32 |= (BIT8 | BIT7);
    657     QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_GLOBAL_PORT, RegData32);
    658 
    659     //
    660     // Sighting #4930653 Required BIOS change on Disconnect vref to change to 600mV.
    661     //
    662     RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_COMPBG);
    663     RegData32 &= ~(BIT10 | BIT9 | BIT8 | BIT7);
    664     RegData32 |= (BIT10 | BIT7);
    665     QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_COMPBG, RegData32);
    666 
    667     // Sideband register write to USB AFE (Phy)
    668     // (pllbypass) to bypass/Disable PLL before switch
    669     RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);
    670     RegData32 |= BIT29;
    671     QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);
    672 
    673     // Sideband register write to USB AFE (Phy)
    674     // (coreclksel) to select 120MHz (ickusbcoreclk) clk source.
    675     // (Default 0 to select 96MHz (ickusbclk96_npad/ppad))
    676     RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1);
    677     RegData32 |= BIT1;
    678     QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1, RegData32);
    679 
    680     // Sideband register write to USB AFE (Phy)
    681     // (divide by 8) to achieve internal 480MHz clock
    682     // for 120MHz input refclk.  (Default: 4'b1000 (divide by 10) for 96MHz)
    683     RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1);
    684     RegData32 &= ~(BIT5 | BIT4 | BIT3);
    685     RegData32 |= BIT6;
    686     QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1, RegData32);
    687 
    688     // Sideband register write to USB AFE (Phy)
    689     // Clear (pllbypass)
    690     RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);
    691     RegData32 &= ~BIT29;
    692     QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);
    693 
    694     // Sideband register write to USB AFE (Phy)
    695     // Set (startlock) to force the PLL FSM to restart the lock
    696     // sequence due to input clock/freq switch.
    697     RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);
    698     RegData32 |= BIT24;
    699     QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);
    700 
    701     // At this point the PLL FSM and COMP FSM will complete
    702 
    703 }
    704 
    705 /**
    706   This function provides early platform Thermal sensor initialisation.
    707 **/
    708 VOID
    709 EFIAPI
    710 EarlyPlatformThermalSensorInit (
    711   VOID
    712   )
    713 {
    714   DEBUG ((EFI_D_INFO, "Early Platform Thermal Sensor Init\n"));
    715 
    716   //
    717   // Set Thermal sensor mode.
    718   //
    719   QNCThermalSensorSetRatiometricMode ();
    720 
    721   //
    722   // Enable RMU Thermal sensor with a Catastrophic Trip point.
    723   //
    724   QNCThermalSensorEnableWithCatastrophicTrip (PLATFORM_CATASTROPHIC_TRIP_CELSIUS);
    725 
    726   //
    727   // Lock all RMU Thermal sensor control & trip point registers.
    728   //
    729   QNCThermalSensorLockAllRegisters ();
    730 }
    731 
    732 /**
    733   Print early platform info messages includeing the Stage1 module that's
    734   running, MFH item list and platform data item list.
    735 **/
    736 VOID
    737 EFIAPI
    738 EarlyPlatformInfoMessages (
    739   VOID
    740   )
    741 {
    742   DEBUG_CODE_BEGIN ();
    743   QUARK_EDKII_STAGE1_HEADER       *Edk2ImageHeader;
    744 
    745   //
    746   // Find which 'Stage1' image we are running and print the details
    747   //
    748   Edk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) PcdGet32 (PcdEsramStage1Base);
    749   DEBUG ((EFI_D_INFO, "\n************************************************************\n"));
    750 
    751   switch ((UINT8)Edk2ImageHeader->ImageIndex & QUARK_STAGE1_IMAGE_TYPE_MASK) {
    752     case QUARK_STAGE1_BOOT_IMAGE_TYPE:
    753       DEBUG ((EFI_D_INFO, "****  Quark EDKII Stage 1 Boot Image %d                ****\n", ((UINT8)Edk2ImageHeader->ImageIndex & ~(QUARK_STAGE1_IMAGE_TYPE_MASK))));
    754       break;
    755 
    756     case QUARK_STAGE1_RECOVERY_IMAGE_TYPE:
    757       DEBUG ((EFI_D_INFO, "****  Quark EDKII Stage 1 Recovery Image %d            ****\n", ((UINT8)Edk2ImageHeader->ImageIndex & ~(QUARK_STAGE1_IMAGE_TYPE_MASK))));
    758       break;
    759 
    760     default:
    761       DEBUG ((EFI_D_INFO, "****  Quark EDKII Unknown Stage 1 Image !!!!           ****\n"));
    762       break;
    763   }
    764   DEBUG (
    765     (EFI_D_INFO,
    766     "****  Quark EDKII Stage 2 Image 0x%08X:0x%08X ****\n" ,
    767     (UINTN) PcdGet32 (PcdFlashFvMainBase),
    768     (UINTN) PcdGet32 (PcdFlashFvMainSize)
    769     ));
    770 
    771   DEBUG (
    772     (EFI_D_INFO,
    773     "****  Quark EDKII Payload Image 0x%08X:0x%08X ****\n" ,
    774     (UINTN) PcdGet32 (PcdFlashFvPayloadBase),
    775     (UINTN) PcdGet32 (PcdFlashFvPayloadSize)
    776     ));
    777 
    778   DEBUG ((EFI_D_INFO, "************************************************************\n\n"));
    779 
    780   DEBUG_CODE_END ();
    781 }
    782 
    783 /**
    784   Check if system reset due to error condition.
    785 
    786   @param  ClearErrorBits  If TRUE clear error flags and value bits.
    787 
    788   @retval TRUE  if system reset due to error condition.
    789   @retval FALSE if NO reset error conditions.
    790 **/
    791 BOOLEAN
    792 CheckForResetDueToErrors (
    793   IN BOOLEAN                              ClearErrorBits
    794   )
    795 {
    796   UINT32                            RegValue;
    797   BOOLEAN                           ResetDueToError;
    798 
    799   ResetDueToError = FALSE;
    800 
    801   //
    802   // Check if RMU reset system due to access violations.
    803   // RMU updates a SOC Unit register before resetting the system.
    804   //
    805   RegValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW);
    806   if ((RegValue & B_CFG_STICKY_RW_VIOLATION) != 0) {
    807     ResetDueToError = TRUE;
    808 
    809     DEBUG (
    810       (EFI_D_ERROR,
    811       "\nReset due to access violation: %s %s %s %s\n",
    812       ((RegValue & B_CFG_STICKY_RW_IMR_VIOLATION) != 0) ? L"'IMR'" : L".",
    813       ((RegValue & B_CFG_STICKY_RW_DECC_VIOLATION) != 0) ? L"'DECC'" : L".",
    814       ((RegValue & B_CFG_STICKY_RW_SMM_VIOLATION) != 0) ? L"'SMM'" : L".",
    815       ((RegValue & B_CFG_STICKY_RW_HMB_VIOLATION) != 0) ? L"'HMB'" : L"."
    816       ));
    817 
    818     //
    819     // Clear error bits.
    820     //
    821     if (ClearErrorBits) {
    822       RegValue &= ~(B_CFG_STICKY_RW_VIOLATION);
    823       QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW, RegValue);
    824     }
    825   }
    826 
    827   return ResetDueToError;
    828 }
    829 
    830 /**
    831   This function provides early platform initialization.
    832 
    833   @param  PlatformInfo  Pointer to platform Info structure.
    834 
    835 **/
    836 VOID
    837 EFIAPI
    838 EarlyPlatformInit (
    839   VOID
    840   )
    841 {
    842   EFI_PLATFORM_TYPE                 PlatformType;
    843 
    844   PlatformType = (EFI_PLATFORM_TYPE) PcdGet16 (PcdPlatformType);
    845 
    846   DEBUG ((EFI_D_INFO, "EarlyPlatformInit for PlatType=0x%02x\n", (UINTN) PlatformType));
    847 
    848   //
    849   // Check if system reset due to error condition.
    850   //
    851   if (CheckForResetDueToErrors (TRUE)) {
    852     if(FeaturePcdGet (WaitIfResetDueToError)) {
    853       DEBUG ((EFI_D_ERROR, "Wait 10 seconds.\n"));
    854       MicroSecondDelay(10000000);
    855     }
    856   }
    857 
    858   //
    859   // Display platform info messages.
    860   //
    861   EarlyPlatformInfoMessages ();
    862 
    863   //
    864   // Early Legacy Gpio Init.
    865   //
    866   EarlyPlatformLegacyGpioInit (PlatformType);
    867 
    868   //
    869   // Early platform Legacy GPIO manipulation depending on GPIOs
    870   // setup by EarlyPlatformLegacyGpioInit.
    871   //
    872   EarlyPlatformLegacyGpioManipulation (PlatformType);
    873 
    874   //
    875   // Early platform specific GPIO Controller init & manipulation.
    876   // Combined for sharing of temp. memory bar.
    877   //
    878   EarlyPlatformGpioCtrlerInitAndManipulation (PlatformType);
    879 
    880   //
    881   // Early Thermal Sensor Init.
    882   //
    883   EarlyPlatformThermalSensorInit ();
    884 
    885   //
    886   // Early Lan Ethernet Mac Init.
    887   //
    888   EarlyPlatformMacInit (
    889     PcdGetPtr (PcdIohEthernetMac0),
    890     PcdGetPtr (PcdIohEthernetMac1)
    891     );
    892 }
    893 
    894 /**
    895   This function provides early platform Legacy GPIO initialisation.
    896 
    897   @param  PlatformType  Platform type for GPIO init.
    898 
    899 **/
    900 VOID
    901 EFIAPI
    902 EarlyPlatformLegacyGpioInit (
    903   IN CONST EFI_PLATFORM_TYPE              PlatformType
    904   )
    905 {
    906   BOARD_LEGACY_GPIO_CONFIG          *LegacyGpioConfig;
    907   UINT32                            NewValue;
    908   UINT32                            GpioBaseAddress;
    909 
    910   //
    911   // Assert if platform type outside table range.
    912   //
    913   ASSERT ((UINTN) PlatformType < mBoardLegacyGpioConfigTableLen);
    914   LegacyGpioConfig = &mBoardLegacyGpioConfigTable[(UINTN) PlatformType];
    915 
    916   GpioBaseAddress = (UINT32)PcdGet16 (PcdGbaIoBaseAddress);
    917 
    918   NewValue     = 0x0;
    919   //
    920   // Program QNC GPIO Registers.
    921   //
    922   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGEN_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellEnable;
    923   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGEN_CORE_WELL, NewValue );
    924   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGIO_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellIoSelect;
    925   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGIO_CORE_WELL, NewValue);
    926   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGLVL_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellLvlForInputOrOutput;
    927   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGLVL_CORE_WELL, NewValue);
    928   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTPE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerPositiveEdge;
    929   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTPE_CORE_WELL, NewValue );
    930   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTNE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerNegativeEdge;
    931   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTNE_CORE_WELL, NewValue);
    932   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGGPE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellGPEEnable;
    933   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGGPE_CORE_WELL, NewValue);
    934   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGSMI_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellSMIEnable;
    935   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGSMI_CORE_WELL, NewValue );
    936   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTS_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerStatus;
    937   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTS_CORE_WELL, NewValue);
    938   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CNMIEN_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellNMIEnable;
    939   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CNMIEN_CORE_WELL, NewValue);
    940 
    941   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGEN_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellEnable;
    942   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGEN_RESUME_WELL, NewValue );
    943   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGIO_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellIoSelect;
    944   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGIO_RESUME_WELL, NewValue) ;
    945   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellLvlForInputOrOutput;
    946   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL, NewValue);
    947   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTPE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerPositiveEdge;
    948   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTPE_RESUME_WELL, NewValue );
    949   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTNE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerNegativeEdge;
    950   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTNE_RESUME_WELL, NewValue) ;
    951   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGGPE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellGPEEnable;
    952   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGGPE_RESUME_WELL, NewValue);
    953   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGSMI_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellSMIEnable;
    954   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGSMI_RESUME_WELL, NewValue );
    955   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTS_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerStatus;
    956   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTS_RESUME_WELL, NewValue) ;
    957   NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RNMIEN_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellNMIEnable;
    958   IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RNMIEN_RESUME_WELL, NewValue);
    959 }
    960 
    961 /**
    962   Performs any early platform specific Legacy GPIO manipulation.
    963 
    964   @param  PlatformType  Platform type GPIO manipulation.
    965 
    966 **/
    967 VOID
    968 EFIAPI
    969 EarlyPlatformLegacyGpioManipulation (
    970   IN CONST EFI_PLATFORM_TYPE              PlatformType
    971   )
    972 {
    973   if (PlatformType == CrossHill) {
    974 
    975     //
    976     // Pull TPM reset low for 80us (equivalent to cold reset, Table 39
    977     // Infineon SLB9645 Databook), then pull TPM reset high and wait for
    978     // 150ms to give time for TPM to stabilise (Section 4.7.1 Infineon
    979     // SLB9645 Databook states TPM is ready to receive command after 30ms
    980     // but section 4.7 states some TPM commands may take longer to execute
    981     // upto 150ms after test).
    982     //
    983 
    984     PlatformLegacyGpioSetLevel (
    985       R_QNC_GPIO_RGLVL_RESUME_WELL,
    986       PLATFORM_RESUMEWELL_TPM_RST_GPIO,
    987       FALSE
    988       );
    989     MicroSecondDelay (80);
    990 
    991     PlatformLegacyGpioSetLevel (
    992       R_QNC_GPIO_RGLVL_RESUME_WELL,
    993       PLATFORM_RESUMEWELL_TPM_RST_GPIO,
    994       TRUE
    995       );
    996     MicroSecondDelay (150000);
    997   }
    998 
    999 }
   1000 
   1001 /**
   1002   Performs any early platform specific GPIO Controller init & manipulation.
   1003 
   1004   @param  PlatformType  Platform type for GPIO init & manipulation.
   1005 
   1006 **/
   1007 VOID
   1008 EFIAPI
   1009 EarlyPlatformGpioCtrlerInitAndManipulation (
   1010   IN CONST EFI_PLATFORM_TYPE              PlatformType
   1011   )
   1012 {
   1013   UINT32                            IohGpioBase;
   1014   UINT32                            Data32;
   1015   UINT32                            Addr;
   1016   BOARD_GPIO_CONTROLLER_CONFIG      *GpioConfig;
   1017   UINT32                            DevPcieAddr;
   1018   UINT16                            SaveCmdReg;
   1019   UINT32                            SaveBarReg;
   1020   UINT16                            PciVid;
   1021   UINT16                            PciDid;
   1022 
   1023   ASSERT ((UINTN) PlatformType < mBoardGpioControllerConfigTableLen);
   1024   GpioConfig = &mBoardGpioControllerConfigTable[(UINTN) PlatformType];
   1025 
   1026   IohGpioBase = (UINT32) PcdGet64 (PcdIohGpioMmioBase);
   1027 
   1028   DevPcieAddr = PCI_LIB_ADDRESS (
   1029                   PcdGet8 (PcdIohGpioBusNumber),
   1030                   PcdGet8 (PcdIohGpioDevNumber),
   1031                   PcdGet8 (PcdIohGpioFunctionNumber),
   1032                   0
   1033                   );
   1034 
   1035   //
   1036   // Do nothing if not a supported device.
   1037   //
   1038   PciVid = PciRead16 (DevPcieAddr + PCI_VENDOR_ID_OFFSET);
   1039   PciDid = PciRead16 (DevPcieAddr + PCI_DEVICE_ID_OFFSET);
   1040   if((PciVid != V_IOH_I2C_GPIO_VENDOR_ID) || (PciDid != V_IOH_I2C_GPIO_DEVICE_ID)) {
   1041     return;
   1042   }
   1043 
   1044   //
   1045   // Save current settings for PCI CMD/BAR registers.
   1046   //
   1047   SaveCmdReg = PciRead16 (DevPcieAddr + PCI_COMMAND_OFFSET);
   1048   SaveBarReg = PciRead32 (DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister));
   1049 
   1050   //
   1051   // Use predefined temporary memory resource.
   1052   //
   1053   PciWrite32 ( DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister), IohGpioBase);
   1054   PciWrite8 ( DevPcieAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
   1055 
   1056   //
   1057   // Gpio Controller Init Tasks.
   1058   //
   1059 
   1060   //
   1061   // IEN- Interrupt Enable Register
   1062   //
   1063   Addr =  IohGpioBase + GPIO_INTEN;
   1064   Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
   1065   Data32 |= (GpioConfig->IntEn & 0x000FFFFF);
   1066   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1067 
   1068   //
   1069   // ISTATUS- Interrupt Status Register
   1070   //
   1071   Addr =  IohGpioBase + GPIO_INTSTATUS;
   1072   Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
   1073   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1074 
   1075   //
   1076   // GPIO SWPORTA Direction Register - GPIO_SWPORTA_DR
   1077   //
   1078   Addr =  IohGpioBase + GPIO_SWPORTA_DR;
   1079   Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
   1080   Data32 |= (GpioConfig->PortADR & 0x000FFFFF);
   1081   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1082 
   1083   //
   1084   // GPIO SWPORTA Data Direction Register - GPIO_SWPORTA_DDR - default input
   1085   //
   1086   Addr =  IohGpioBase + GPIO_SWPORTA_DDR;
   1087   Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
   1088   Data32 |= (GpioConfig->PortADir & 0x000FFFFF);
   1089   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1090 
   1091   //
   1092   // Interrupt Mask Register - GPIO_INTMASK - default interrupts unmasked
   1093   //
   1094   Addr =  IohGpioBase + GPIO_INTMASK;
   1095   Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
   1096   Data32 |= (GpioConfig->IntMask & 0x000FFFFF);
   1097   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1098 
   1099   //
   1100   // Interrupt Level Type Register - GPIO_INTTYPE_LEVEL - default is level sensitive
   1101   //
   1102   Addr =  IohGpioBase + GPIO_INTTYPE_LEVEL;
   1103   Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
   1104   Data32 |= (GpioConfig->IntType & 0x000FFFFF);
   1105   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1106 
   1107   //
   1108   // Interrupt Polarity Type Register - GPIO_INT_POLARITY - default is active low
   1109   //
   1110   Addr =  IohGpioBase + GPIO_INT_POLARITY;
   1111   Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
   1112   Data32 |= (GpioConfig->IntPolarity & 0x000FFFFF);
   1113   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1114 
   1115   //
   1116   // Interrupt Debounce Type Register - GPIO_DEBOUNCE - default no debounce
   1117   //
   1118   Addr =  IohGpioBase + GPIO_DEBOUNCE;
   1119   Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
   1120   Data32 |= (GpioConfig->Debounce & 0x000FFFFF);
   1121   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1122 
   1123   //
   1124   // Interrupt Clock Synchronisation Register - GPIO_LS_SYNC - default no sync with pclk_intr(APB bus clk)
   1125   //
   1126   Addr =  IohGpioBase + GPIO_LS_SYNC;
   1127   Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]
   1128   Data32 |= (GpioConfig->LsSync & 0x000FFFFF);
   1129   *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1130 
   1131   //
   1132   // Gpio Controller Manipulation Tasks.
   1133   //
   1134 
   1135   if (PlatformType == (EFI_PLATFORM_TYPE) Galileo) {
   1136     //
   1137     // Reset Cypress Expander on Galileo Platform
   1138     //
   1139     Addr = IohGpioBase + GPIO_SWPORTA_DR;
   1140     Data32 = *((volatile UINT32 *) (UINTN)(Addr));
   1141     Data32 |= BIT4;                                 // Cypress Reset line controlled by GPIO<4>
   1142     *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1143 
   1144     Data32 = *((volatile UINT32 *) (UINTN)(Addr));
   1145     Data32 &= ~BIT4;                                // Cypress Reset line controlled by GPIO<4>
   1146     *((volatile UINT32 *) (UINTN)(Addr)) = Data32;
   1147 
   1148   }
   1149 
   1150   //
   1151   // Restore settings for PCI CMD/BAR registers
   1152   //
   1153   PciWrite32 ((DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister)), SaveBarReg);
   1154   PciWrite16 (DevPcieAddr + PCI_COMMAND_OFFSET, SaveCmdReg);
   1155 }
   1156 
   1157 /**
   1158   Performs any early platform init of SoC Ethernet Mac devices.
   1159 
   1160   @param  IohMac0Address  Mac address to program into Mac0 device.
   1161   @param  IohMac1Address  Mac address to program into Mac1 device.
   1162 
   1163 **/
   1164 VOID
   1165 EFIAPI
   1166 EarlyPlatformMacInit (
   1167   IN CONST UINT8                          *IohMac0Address,
   1168   IN CONST UINT8                          *IohMac1Address
   1169   )
   1170 {
   1171   BOOLEAN                           SetMacAddr;
   1172 
   1173   //
   1174   // Set chipset MAC0 address if configured.
   1175   //
   1176   SetMacAddr =
   1177     (CompareMem (ChipsetDefaultMac, IohMac0Address, sizeof (ChipsetDefaultMac))) != 0;
   1178   if (SetMacAddr) {
   1179     if ((*(IohMac0Address) & BIT0) != 0) {
   1180       DEBUG ((EFI_D_ERROR, "HALT: Multicast Mac Address configured for Ioh MAC [B:%d, D:%d, F:%d]\n",
   1181         (UINTN) IOH_MAC0_BUS_NUMBER,
   1182         (UINTN) IOH_MAC0_DEVICE_NUMBER,
   1183         (UINTN) IOH_MAC0_FUNCTION_NUMBER
   1184         ));
   1185       ASSERT (FALSE);
   1186     } else {
   1187       SetLanControllerMacAddr (
   1188         IOH_MAC0_BUS_NUMBER,
   1189         IOH_MAC0_DEVICE_NUMBER,
   1190         IOH_MAC0_FUNCTION_NUMBER,
   1191         IohMac0Address,
   1192         (UINT32) PcdGet64(PcdIohMac0MmioBase)
   1193         );
   1194     }
   1195   } else {
   1196     DEBUG ((EFI_D_WARN, "WARNING: Ioh MAC [B:%d, D:%d, F:%d] NO HW ADDR CONFIGURED!!!\n",
   1197       (UINTN) IOH_MAC0_BUS_NUMBER,
   1198       (UINTN) IOH_MAC0_DEVICE_NUMBER,
   1199       (UINTN) IOH_MAC0_FUNCTION_NUMBER
   1200       ));
   1201   }
   1202 
   1203   //
   1204   // Set chipset MAC1 address if configured.
   1205   //
   1206   SetMacAddr =
   1207     (CompareMem (ChipsetDefaultMac, IohMac1Address, sizeof (ChipsetDefaultMac))) != 0;
   1208   if (SetMacAddr) {
   1209     if ((*(IohMac1Address) & BIT0) != 0) {
   1210       DEBUG ((EFI_D_ERROR, "HALT: Multicast Mac Address configured for Ioh MAC [B:%d, D:%d, F:%d]\n",
   1211         (UINTN) IOH_MAC1_BUS_NUMBER,
   1212         (UINTN) IOH_MAC1_DEVICE_NUMBER,
   1213         (UINTN) IOH_MAC1_FUNCTION_NUMBER
   1214         ));
   1215       ASSERT (FALSE);
   1216     } else {
   1217         SetLanControllerMacAddr (
   1218           IOH_MAC1_BUS_NUMBER,
   1219           IOH_MAC1_DEVICE_NUMBER,
   1220           IOH_MAC1_FUNCTION_NUMBER,
   1221           IohMac1Address,
   1222           (UINT32) PcdGet64(PcdIohMac1MmioBase)
   1223           );
   1224     }
   1225   } else {
   1226     DEBUG ((EFI_D_WARN, "WARNING: Ioh MAC [B:%d, D:%d, F:%d] NO HW ADDR CONFIGURED!!!\n",
   1227       (UINTN) IOH_MAC1_BUS_NUMBER,
   1228       (UINTN) IOH_MAC1_DEVICE_NUMBER,
   1229       (UINTN) IOH_MAC1_FUNCTION_NUMBER
   1230       ));
   1231   }
   1232 }
   1233 
   1234