Home | History | Annotate | Download | only in PlatformPei
      1 /** @file
      2 
      3   Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
      4 
      5   This program and the accompanying materials are licensed and made available under
      7   the terms and conditions of the BSD License that accompanies this distribution.
      9   The full text of the license may be found at
     11   http://opensource.org/licenses/bsd-license.php.
     13 
     15   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.
     19 
     21 
     23 
     24 Module Name:
     25 
     26 **/
     27 
     28 #include "CommonHeader.h"
     29 
     30 #include "Platform.h"
     31 #include <Library/PciCf8Lib.h>
     32 #include "PlatformBaseAddresses.h"
     33 #include "PchAccess.h"
     34 #include <Guid/PlatformInfo.h>
     35 #include "Platform.h"
     36 #include "PchCommonDefinitions.h"
     37 #include <Ppi/MfgMemoryTest.h>
     38 #include <Guid/SetupVariable.h>
     39 #include <Guid/Vlv2Variable.h>
     40 #include <Ppi/fTPMPolicy.h>
     41 
     42 //
     43 // Start::Alpine Valley platform
     44 //
     45 enum {
     46   SMBUS_READ_BYTE,
     47   SMBUS_WRITE_BYTE,
     48   SMBUS_READ_BLOCK,
     49   SMBUS_WRITE_BLOCK
     50 };
     51 
     52 #define EC_BASE           0xE0000000
     53 
     54 //
     55 // DEVICE 0 (Memroy Controller Hub)
     56 //
     57 #define MC_BUS              0x00
     58 #define MC_DEV              0x00
     59 #define MC_FUN              0x00
     60 #define MC_DEV_FUN          (MC_DEV << 3)
     61 #define MC_BUS_DEV_FUN      ((MC_BUS << 8) + MC_DEV_FUN)
     62 
     63 //
     64 // SysCtl SMBus address and block size
     65 //
     66 #define AV_SC_SMBUS_ADDRESS        	0x60
     67 #define AV_SC_BYTE_LEN            	1
     68 #define AV_SC_BLOCK_LEN            	4
     69 #define AV_SC_SMBUS_WRCMD           1
     70 #define AV_SC_SMBUS_RDCMD           0
     71 
     72 //
     73 // SysCtl registers offset
     74 //
     75 #define AV_SC_REG_PLATFORM_ID               24  // 0x18
     76 #define AV_SC_REG_BOARD_ID                  28  // 0x1C
     77 #define AV_SC_REG_FAB_ID                    32  // 0x20
     78 #define AV_SC_REG_ECO_ID                    68  // 0x44
     79 #define AV_SC_REG_DDR_DAUGHTER_CARD_ID      144 // 0x90
     80 #define AV_SC_REG_SODIMM_CONFIG             36
     81 
     82 //
     83 // ID values
     84 //
     85 #define AV_SC_PLATFORM_ID_TABLET   0
     86 #define AV_SC_PLATFORM_ID_NETBOOK  2
     87 #define AV_SC_PLATFORM_ID_INTERPOSER 3 // Configuration TBD
     88 #define AV_SC_BOARD_ID_AV_SVP      1492
     89 
     90 #define BUS_TRIES                 3       // How many times to retry on Bus Errors
     91 
     92 #define GTT_SIZE_1MB        1
     93 #define GTT_SIZE_2MB        2
     94 
     95 #define PciCfg16Read( PciExpressBase, Bus, Device, Function, Register ) \
     96   MmioRead16(PciExpressBase + \
     97     (UINTN)(Bus << 20) + \
     98     (UINTN)(Device << 15) + \
     99     (UINTN)(Function << 12) + \
    100     (UINTN)(Register))
    101 #define PciCfg16Write( PciExpressBase, Bus, Device, Function, Register, Data ) \
    102     MmioWrite16(PciExpressBase + \
    103       (UINTN)(Bus << 20) + \
    104       (UINTN)(Device << 15) + \
    105       (UINTN)(Function << 12) + \
    106       (UINTN)(Register), \
    107       (UINT16)Data)
    108 
    109 
    110 //
    111 //Memory Test Manufacturing mode
    112 //
    113 UINT32 DataPatternForMemoryTest[] = {
    114     0x55555555, 0xAAAAAAAA, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF, 0x55555510, 0x555555EF,
    115     0x55555555, 0xAAAAAAAA, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55, 0x55551055, 0x5555EF55,
    116     0x55555555, 0xAAAAAAAA, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555, 0x55105555, 0x55EF5555,
    117     0x55555555, 0xAAAAAAAA, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555, 0x10555555, 0xEF555555
    118 };
    119 #define DATA_PATTERN_ARRAY_SIZE (sizeof(DataPatternForMemoryTest) / sizeof(UINT32))
    120 
    121 //
    122 //Memory Test Manufacturing mode
    123 //
    124 //
    125 // The global indicator, the FvFileLoader callback will modify it to TRUE after loading PEIM into memory
    126 //
    127 BOOLEAN ImageInMemory = FALSE;
    128 
    129 EFI_STATUS
    130 EFIAPI
    131 Stall (
    132   IN CONST EFI_PEI_SERVICES   **PeiServices,
    133   IN CONST EFI_PEI_STALL_PPI      *This,
    134   IN UINTN              Microseconds
    135   );
    136 
    137 EFI_STATUS
    138 EFIAPI
    139 MfgMemoryTest (
    140   IN  CONST EFI_PEI_SERVICES                   **PeiServices,
    141   IN  PEI_MFG_MEMORY_TEST_PPI           *This,
    142   IN  UINT32                             BeginAddress,
    143   IN  UINT32                             MemoryLength
    144   );
    145 
    146 static EFI_PEI_STALL_PPI  mStallPpi = {
    147   PEI_STALL_RESOLUTION,
    148   Stall
    149 };
    150 
    151 static PEI_MFG_MEMORY_TEST_PPI mPeiMfgMemoryTestPpi = {
    152   MfgMemoryTest
    153 };
    154 
    155 static EFI_PEI_PPI_DESCRIPTOR mInstallStallPpi[] = {
    156   {
    157   EFI_PEI_PPI_DESCRIPTOR_PPI,
    158   &gEfiPeiStallPpiGuid,
    159   &mStallPpi
    160   },
    161   {
    162     EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
    163     &gPeiMfgMemoryTestPpiGuid,
    164     &mPeiMfgMemoryTestPpi
    165   }
    166  };
    167 
    168 EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = {
    169   {
    170     (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
    171     &gEfiPeiMemoryDiscoveredPpiGuid,
    172     MemoryDiscoveredPpiNotifyCallback
    173   }
    174 };
    175 
    176 EFI_STATUS
    177 EFIAPI
    178 InstallMonoStatusCode (
    179   IN EFI_FFS_FILE_HEADER       *FfsHeader,
    180   IN CONST EFI_PEI_SERVICES          **PeiServices
    181   );
    182 
    183 
    184 EFI_STATUS
    185 ReadPlatformIds (
    186   IN CONST EFI_PEI_SERVICES             **PeiServices,
    187   IN OUT EFI_PLATFORM_INFO_HOB          *PlatformInfoHob
    188   );
    189 
    190 //
    191 // Start::Alpine Valley platform
    192 //
    193 EFI_STATUS
    194 PeiSmbusExec (
    195   UINT16 SmbusBase,
    196   UINT8 SlvAddr,
    197   UINT8 Operation,
    198   UINT8 Offset,
    199   UINT8 *Length,
    200   UINT8 *Buffer
    201   );
    202 
    203 
    204 /**
    205 
    206   Detemine Turbot board
    207   @return 0: Not Turbot board
    208           1: Turbot board
    209 
    210 **/
    211 UINT32
    212 DetermineTurbotBoard (
    213   void
    214   )
    215 {
    216   UINTN PciD31F0RegBase = 0;
    217   UINT32 GpioValue = 0;
    218   UINT32 TmpVal = 0;
    219   UINT32 MmioConf0 = 0;
    220   UINT32 MmioPadval = 0;
    221   UINT32 PConf0Offset = 0x200; //GPIO_S5_4 pad_conf0 register offset
    222   UINT32 PValueOffset = 0x208; //GPIO_S5_4 pad_value register offset
    223   UINT32 SSUSOffset = 0x2000;
    224   UINT32 IoBase = 0;
    225 
    226   DEBUG ((EFI_D_ERROR, "DetermineTurbotBoard() Entry\n"));
    227   PciD31F0RegBase = MmPciAddress (0,
    228                       0,
    229                       PCI_DEVICE_NUMBER_PCH_LPC,
    230                       PCI_FUNCTION_NUMBER_PCH_LPC,
    231                       0
    232                     );
    233   IoBase = MmioRead32 (PciD31F0RegBase + R_PCH_LPC_IO_BASE) & B_PCH_LPC_IO_BASE_BAR;
    234 
    235   MmioConf0 = IoBase + SSUSOffset + PConf0Offset;
    236   MmioPadval = IoBase + SSUSOffset + PValueOffset;
    237   //0xFED0E200/0xFED0E208 is pad_Conf/pad_val register address of GPIO_S5_4
    238   DEBUG ((EFI_D_ERROR, "MmioConf0[0x%x], MmioPadval[0x%x]\n", MmioConf0, MmioPadval));
    239 
    240   MmioWrite32 (MmioConf0, 0x2003CC00);
    241 
    242   TmpVal = MmioRead32 (MmioPadval);
    243   TmpVal &= ~0x6; //Clear bit 1:2
    244   TmpVal |= 0x2; // Set the pin as GPI
    245   MmioWrite32 (MmioPadval, TmpVal);
    246 
    247   GpioValue = MmioRead32 (MmioPadval);
    248 
    249   DEBUG ((EFI_D_ERROR, "Gpio_S5_4 value is 0x%x\n", GpioValue));
    250   return (GpioValue & 0x1);
    251 }
    252 
    253 
    254 
    255 EFI_STATUS
    256 FtpmPolicyInit (
    257   IN CONST EFI_PEI_SERVICES             **PeiServices,
    258   IN SYSTEM_CONFIGURATION         *pSystemConfiguration
    259   )
    260 {
    261   EFI_STATUS                      Status;
    262   EFI_PEI_PPI_DESCRIPTOR          *mFtpmPolicyPpiDesc;
    263   SEC_FTPM_POLICY_PPI             *mFtpmPolicyPpi;
    264 
    265 
    266   DEBUG((EFI_D_INFO, "FtpmPolicyInit Entry \n"));
    267 
    268   if (NULL == PeiServices ||  NULL == pSystemConfiguration) {
    269     DEBUG((EFI_D_ERROR, "Input error. \n"));
    270     return EFI_INVALID_PARAMETER;
    271   }
    272 
    273   Status = (*PeiServices)->AllocatePool(
    274                              PeiServices,
    275                              sizeof (EFI_PEI_PPI_DESCRIPTOR),
    276                              (void **)&mFtpmPolicyPpiDesc
    277                              );
    278   ASSERT_EFI_ERROR (Status);
    279 
    280   Status = (*PeiServices)->AllocatePool(
    281                              PeiServices,
    282                              sizeof (SEC_FTPM_POLICY_PPI),
    283                              (void **)&mFtpmPolicyPpi
    284                              );
    285   ASSERT_EFI_ERROR (Status);
    286 
    287   //
    288   // Initialize PPI
    289   //
    290   (*PeiServices)->SetMem ((VOID *)mFtpmPolicyPpi, sizeof (SEC_FTPM_POLICY_PPI), 0);
    291   mFtpmPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
    292   mFtpmPolicyPpiDesc->Guid = &gSeCfTPMPolicyPpiGuid;
    293   mFtpmPolicyPpiDesc->Ppi = mFtpmPolicyPpi;
    294 
    295 
    296   DEBUG((EFI_D_INFO, "pSystemConfiguration->fTPM = 0x%x \n", pSystemConfiguration->fTPM));
    297   if(pSystemConfiguration->fTPM == 1) {
    298     mFtpmPolicyPpi->fTPMEnable = TRUE;
    299   } else {
    300     mFtpmPolicyPpi->fTPMEnable = FALSE;
    301   }
    302 
    303   Status = (*PeiServices)->InstallPpi(
    304                              PeiServices,
    305                              mFtpmPolicyPpiDesc
    306                              );
    307   ASSERT_EFI_ERROR (Status);
    308 
    309   DEBUG((EFI_D_INFO, "FtpmPolicyInit done \n"));
    310 
    311   return EFI_SUCCESS;
    312 }
    313 
    314 
    315 /**
    316   This routine attempts to acquire the SMBus
    317 
    318   @retval FAILURE as failed
    319   @retval SUCCESS as passed
    320 
    321 **/
    322 EFI_STATUS
    323 AcquireBus (
    324     UINT16	SmbusBase
    325   )
    326 {
    327   UINT8 StsReg;
    328 
    329   StsReg  = 0;
    330   StsReg  = (UINT8)IoRead8(SmbusBase + R_PCH_SMBUS_HSTS);
    331   if (StsReg & B_PCH_SMBUS_IUS) {
    332     return EFI_DEVICE_ERROR;
    333   } else if (StsReg & B_PCH_SMBUS_HBSY) {
    334     //
    335     // Clear Status Register and exit
    336     //
    337     // Wait for HSTS.HBSY to be clear
    338 	  //
    339     do { StsReg = (UINT8) IoRead8(SmbusBase+R_PCH_SMBUS_HSTS); } while ((StsReg & B_PCH_SMBUS_HBSY) != 0);
    340 
    341 	  //
    342     // Clear all status bits
    343 	  //
    344     IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, 0xFE);
    345     return EFI_SUCCESS;
    346   } else {
    347     //
    348     // Clear out any odd status information (Will Not Clear In Use)
    349     //
    350     IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, StsReg);
    351     return EFI_SUCCESS;
    352   }
    353 }
    354 //
    355 // End::Alpine Valley platform
    356 //
    357 
    358 /**
    359   This function checks the memory range in PEI.
    360 
    361   @param  PeiServices     Pointer to PEI Services.
    362   @param  This            Pei memory test PPI pointer.
    363   @param  BeginAddress    Beginning of the memory address to be checked.
    364   @param  MemoryLength    Bytes of memory range to be checked.
    365   @param  Operation       Type of memory check operation to be performed.
    366   @param  ErrorAddress    Return the address of the error memory address.
    367 
    368   @retval  EFI_SUCCESS         The operation completed successfully.
    369   @retval  EFI_DEVICE_ERROR    Memory test failed. It's not safe to use this range of memory.
    370 
    371 **/
    372 EFI_STATUS
    373 EFIAPI
    374 MfgMemoryTest (
    375   IN  CONST EFI_PEI_SERVICES                   **PeiServices,
    376   IN  PEI_MFG_MEMORY_TEST_PPI           *This,
    377   IN  UINT32                             BeginAddress,
    378   IN  UINT32                             MemoryLength
    379   )
    380 {
    381   UINT32 i;
    382   UINT32 memAddr;
    383   UINT32 readData;
    384   UINT32 xorData;
    385   UINT32 TestFlag = 0;
    386   memAddr = BeginAddress;
    387 
    388   //
    389   //Output Message for MFG
    390   //
    391   DEBUG ((EFI_D_ERROR, "MFGMODE SET\n"));
    392 
    393   //
    394   //Writting the pattern in defined location.
    395   //
    396   while (memAddr < (BeginAddress+MemoryLength)) {
    397     for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) {
    398       if (memAddr > (BeginAddress+MemoryLength -4)) {
    399         memAddr = memAddr + 4;
    400         break;
    401       }
    402       *((volatile UINT32*) memAddr) = DataPatternForMemoryTest[i];
    403       memAddr = memAddr + 4;
    404     }
    405   }
    406 
    407   //
    408   //Verify the pattern.
    409   //
    410   memAddr = BeginAddress;
    411   while (memAddr < (BeginAddress+MemoryLength)) {
    412   for (i = 0; i < DATA_PATTERN_ARRAY_SIZE; i++) {
    413     if (memAddr > (BeginAddress+MemoryLength -4)) {
    414       memAddr = memAddr + 4;
    415       break;
    416     }
    417     readData = *((volatile UINT32*) memAddr);
    418     xorData = readData ^ DataPatternForMemoryTest[i];
    419 
    420 	  //
    421     // If xorData is nonzero, this particular memAddr has a failure.
    422 	  //
    423     if (xorData != 0x00000000) {
    424       DEBUG ((EFI_D_ERROR, "Expected value....: %x\n", DataPatternForMemoryTest[i]));
    425       DEBUG ((EFI_D_ERROR, "ReadData value....: %x\n", readData));
    426       DEBUG ((EFI_D_ERROR, "Pattern failure at....: %x\n", memAddr));
    427       TestFlag = 1;
    428     }
    429     memAddr = memAddr + 4;
    430     }
    431   }
    432   if (TestFlag) {
    433     return EFI_DEVICE_ERROR;
    434   }
    435 
    436   //
    437   //Output Message for MFG
    438   //
    439   DEBUG ((EFI_D_ERROR, "MFGMODE MEMORY TEST PASSED\n"));
    440   return EFI_SUCCESS;
    441 }
    442 
    443 BOOLEAN
    444 IsRtcUipAlwaysSet (
    445   IN CONST EFI_PEI_SERVICES       **PeiServices
    446   )
    447 {
    448 
    449   EFI_PEI_STALL_PPI *StallPpi;
    450   UINTN             Count;
    451 
    452   (**PeiServices).LocatePpi (PeiServices, &gEfiPeiStallPpiGuid, 0, NULL, (void **)&StallPpi);
    453 
    454   for (Count = 0; Count < 500; Count++) { // Maximum waiting approximates to 1.5 seconds (= 3 msec * 500)
    455     IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA);
    456     if ((IoRead8 (R_PCH_RTC_TARGET2) & B_PCH_RTC_REGISTERA_UIP) == 0) {
    457       return FALSE;
    458     }
    459 
    460     StallPpi->Stall (PeiServices, StallPpi, 3000);
    461   }
    462 
    463   return TRUE;
    464 }
    465 
    466 EFI_STATUS
    467 RtcPowerFailureHandler (
    468   IN CONST EFI_PEI_SERVICES       **PeiServices
    469   )
    470 {
    471 
    472   UINT16          DataUint16;
    473   UINT8           DataUint8;
    474   BOOLEAN         RtcUipIsAlwaysSet;
    475   DataUint16        = MmioRead16 (PMC_BASE_ADDRESS + R_PCH_PMC_GEN_PMCON_1);
    476   RtcUipIsAlwaysSet = IsRtcUipAlwaysSet (PeiServices);
    477   if ((DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) || (RtcUipIsAlwaysSet)) {
    478     //
    479     // Execute the sequence below. This will ensure that the RTC state machine has been initialized.
    480     //
    481     // Step 1.
    482     // BIOS clears this bit by writing a '0' to it.
    483     //
    484     if (DataUint16 & B_PCH_PMC_GEN_PMCON_RTC_PWR_STS) {
    485       //
    486       // Set to invalid date in order to reset the time to
    487       // BIOS build time later in the boot (SBRUN.c file).
    488       //
    489       IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_YEAR);
    490       IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
    491       IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MONTH);
    492       IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
    493       IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFMONTH);
    494       IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
    495       IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_DAYOFWEEK);
    496       IoWrite8 (R_PCH_RTC_TARGET2, 0x0FF);
    497 
    498       IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_SECONDSALARM);
    499       IoWrite8 (R_PCH_RTC_TARGET2, 0x00);
    500       IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_MINUTESALARM);
    501       IoWrite8 (R_PCH_RTC_TARGET2, 0x00);
    502       IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_HOURSALARM);
    503       IoWrite8 (R_PCH_RTC_TARGET2, 0x00);
    504     }
    505 
    506     //
    507     // Step 2.
    508     // Set RTC Register 0Ah[6:4] to '110' or '111'.
    509     //
    510     IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA);
    511     IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_DIV_RST1 | V_PCH_RTC_REGISTERA_RS_976P5US));
    512 
    513     //
    514     // Step 3.
    515     // Set RTC Register 0Bh[7].
    516     //
    517     IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
    518     DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) | B_PCH_RTC_REGISTERB_SET);
    519     IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
    520     IoWrite8 (R_PCH_RTC_TARGET2, DataUint8);
    521 
    522     //
    523     // Step 4.
    524     // Set RTC Register 0Ah[6:4] to '010'.
    525     //
    526     IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERA);
    527     IoWrite8 (R_PCH_RTC_TARGET2, (V_PCH_RTC_REGISTERA_DV_NORM_OP | V_PCH_RTC_REGISTERA_RS_976P5US));
    528 
    529     //
    530     // Step 5.
    531     // Clear RTC Register 0Bh[7].
    532     //
    533     IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
    534     DataUint8 = (IoRead8 (R_PCH_RTC_TARGET2) & (UINT8)~B_PCH_RTC_REGISTERB_SET);
    535     IoWrite8 (R_PCH_RTC_INDEX2, R_PCH_RTC_REGISTERB);
    536     IoWrite8 (R_PCH_RTC_TARGET2, DataUint8);
    537   }
    538 
    539   return EFI_SUCCESS;
    540 }
    541 
    542 
    543 VOID
    544 PchBaseInit (
    545   VOID
    546   )
    547 {
    548   //
    549   // Program ACPI Power Management I/O Space Base Address
    550   //
    551   MmioWrite16 (
    552     MmPciAddress (0,
    553       DEFAULT_PCI_BUS_NUMBER_PCH,
    554       PCI_DEVICE_NUMBER_PCH_LPC,
    555       PCI_FUNCTION_NUMBER_PCH_LPC,
    556       R_PCH_LPC_ACPI_BASE
    557     ),
    558     (UINT16)((ACPI_BASE_ADDRESS & B_PCH_LPC_ACPI_BASE_BAR) | B_PCH_LPC_ACPI_BASE_EN)
    559   );
    560 
    561   //
    562   // Program GPIO Base Address
    563   //
    564   MmioWrite16 (
    565     MmPciAddress (0,
    566       DEFAULT_PCI_BUS_NUMBER_PCH,
    567       PCI_DEVICE_NUMBER_PCH_LPC,
    568       PCI_FUNCTION_NUMBER_PCH_LPC,
    569       R_PCH_LPC_GPIO_BASE
    570     ),
    571     (UINT16)((GPIO_BASE_ADDRESS & B_PCH_LPC_GPIO_BASE_BAR) | B_PCH_LPC_GPIO_BASE_EN)
    572   );
    573 
    574   //
    575   // Set PMC Base Address
    576   //
    577   MmioWrite32 (
    578     MmPciAddress (0,
    579       DEFAULT_PCI_BUS_NUMBER_PCH,
    580       PCI_DEVICE_NUMBER_PCH_LPC,
    581       PCI_FUNCTION_NUMBER_PCH_LPC,
    582       R_PCH_LPC_PMC_BASE
    583     ),
    584     (UINT32)((PMC_BASE_ADDRESS & B_PCH_LPC_PMC_BASE_BAR) | B_PCH_LPC_PMC_BASE_EN)
    585   );
    586 
    587   //
    588   // Set IO Base Address
    589   //
    590   MmioWrite32 (
    591     MmPciAddress (0,
    592       DEFAULT_PCI_BUS_NUMBER_PCH,
    593       PCI_DEVICE_NUMBER_PCH_LPC,
    594       PCI_FUNCTION_NUMBER_PCH_LPC,
    595       R_PCH_LPC_IO_BASE
    596     ),
    597     (UINT32)((IO_BASE_ADDRESS & B_PCH_LPC_IO_BASE_BAR) | B_PCH_LPC_IO_BASE_EN)
    598   );
    599 
    600   //
    601   // Set ILB Base Address
    602   //
    603   MmioWrite32 (
    604     MmPciAddress (0,
    605       DEFAULT_PCI_BUS_NUMBER_PCH,
    606       PCI_DEVICE_NUMBER_PCH_LPC,
    607       PCI_FUNCTION_NUMBER_PCH_LPC,
    608       R_PCH_LPC_ILB_BASE
    609     ),
    610     (UINT32)((ILB_BASE_ADDRESS & B_PCH_LPC_ILB_BASE_BAR) | B_PCH_LPC_ILB_BASE_EN)
    611   );
    612 
    613   //
    614   // Set PUnit Base Address
    615   //
    616   MmioWrite32 (
    617     MmPciAddress (0,
    618       DEFAULT_PCI_BUS_NUMBER_PCH,
    619       PCI_DEVICE_NUMBER_PCH_LPC,
    620       PCI_FUNCTION_NUMBER_PCH_LPC,
    621       R_PCH_LPC_PUNIT_BASE
    622     ),
    623     (UINT32)((PUNIT_BASE_ADDRESS & B_PCH_LPC_PUNIT_BASE_BAR) | B_PCH_LPC_PUNIT_BASE_EN)
    624   );
    625 
    626   //
    627   // Set SPI Base Address
    628   //
    629   MmioWrite32 (
    630     MmPciAddress (0,
    631       DEFAULT_PCI_BUS_NUMBER_PCH,
    632       PCI_DEVICE_NUMBER_PCH_LPC,
    633       PCI_FUNCTION_NUMBER_PCH_LPC,
    634       R_PCH_LPC_SPI_BASE
    635     ),
    636     (UINT32)((SPI_BASE_ADDRESS & B_PCH_LPC_SPI_BASE_BAR) | B_PCH_LPC_SPI_BASE_EN)
    637   );
    638 
    639   //
    640   // Set Root Complex Base Address
    641   //
    642   MmioWrite32 (
    643     MmPciAddress (0,
    644       DEFAULT_PCI_BUS_NUMBER_PCH,
    645       PCI_DEVICE_NUMBER_PCH_LPC,
    646       PCI_FUNCTION_NUMBER_PCH_LPC,
    647       R_PCH_LPC_RCBA
    648     ),
    649     (UINT32)((RCBA_BASE_ADDRESS & B_PCH_LPC_RCBA_BAR) | B_PCH_LPC_RCBA_EN)
    650   );
    651 
    652   //
    653   // Set MPHY Base Address
    654   //
    655   MmioWrite32 (
    656     MmPciAddress (0,
    657       DEFAULT_PCI_BUS_NUMBER_PCH,
    658       PCI_DEVICE_NUMBER_PCH_LPC,
    659       PCI_FUNCTION_NUMBER_PCH_LPC,
    660       R_PCH_LPC_MPHY_BASE
    661     ),
    662     (UINT32)((MPHY_BASE_ADDRESS & B_PCH_LPC_MPHY_BASE_BAR) | B_PCH_LPC_MPHY_BASE_EN)
    663   );
    664   MmioWrite16 (
    665     MmPciAddress (0,
    666       DEFAULT_PCI_BUS_NUMBER_PCH,
    667       PCI_DEVICE_NUMBER_PCH_SMBUS,
    668       PCI_FUNCTION_NUMBER_PCH_SMBUS,
    669       R_PCH_SMBUS_BASE
    670     ),
    671     (UINT16)(SMBUS_BASE_ADDRESS & B_PCH_SMBUS_BASE_BAR)
    672   );
    673 
    674   MmioOr8 (
    675     MmPciAddress (0,
    676       DEFAULT_PCI_BUS_NUMBER_PCH,
    677       PCI_DEVICE_NUMBER_PCH_SMBUS,
    678       PCI_FUNCTION_NUMBER_PCH_SMBUS,
    679       R_PCH_SMBUS_PCICMD
    680     ),
    681     B_PCH_SMBUS_PCICMD_IOSE
    682   );
    683 
    684 }
    685 
    686 /**
    687   This is the entrypoint of PEIM
    688 
    689   @param  FileHandle  Handle of the file being invoked.
    690   @param  PeiServices Describes the list of possible PEI Services.
    691 
    692   @retval EFI_SUCCESS if it completed successfully.
    693 **/
    694 EFI_STATUS
    695 EFIAPI
    696 PeiInitPlatform (
    697   IN       EFI_PEI_FILE_HANDLE  FileHandle,
    698   IN CONST EFI_PEI_SERVICES     **PeiServices
    699   )
    700 {
    701   UINTN                            SmbusRegBase;
    702   EFI_PLATFORM_INFO_HOB            PlatformInfo;
    703   EFI_STATUS                       Status= EFI_SUCCESS;
    704   EFI_PEI_READ_ONLY_VARIABLE2_PPI  *Variable = NULL;
    705   UINTN                            VariableSize;
    706   SYSTEM_CONFIGURATION             SystemConfiguration;
    707   UINT32                           GGC = 0;
    708 
    709   EFI_PEI_PPI_DESCRIPTOR          *mVlvMmioPolicyPpiDesc;
    710   VLV_MMIO_POLICY_PPI             *mVlvMmioPolicyPpi;
    711 
    712   ZeroMem (&PlatformInfo, sizeof(PlatformInfo));
    713 
    714   Status =  InstallMonoStatusCode(FileHandle, PeiServices);
    715   ASSERT_EFI_ERROR (Status);
    716 
    717 
    718   //
    719   // Initialize Stall PPIs
    720   //
    721   Status = (*PeiServices)->InstallPpi (PeiServices, &mInstallStallPpi[0]);
    722   ASSERT_EFI_ERROR (Status);
    723 
    724   Status = (*PeiServices)->NotifyPpi (PeiServices, &mMemoryDiscoveredNotifyList[0]);
    725   ASSERT_EFI_ERROR (Status);
    726   SmbusRegBase = PchPciDeviceMmBase (
    727                    DEFAULT_PCI_BUS_NUMBER_PCH,
    728                    PCI_DEVICE_NUMBER_PCH_SMBUS,
    729                    PCI_FUNCTION_NUMBER_PCH_SMBUS
    730                    );
    731   //
    732   // Since PEI has no PCI enumerator, set the BAR & I/O space enable ourselves
    733   //
    734   MmioAndThenOr32 (SmbusRegBase + R_PCH_SMBUS_BASE, B_PCH_SMBUS_BASE_BAR, SMBUS_BASE_ADDRESS);
    735 
    736   MmioOr8 (SmbusRegBase + R_PCH_SMBUS_PCICMD, B_PCH_SMBUS_PCICMD_IOSE);
    737 
    738   PchBaseInit();
    739 
    740   //
    741   //Todo: confirm if we need program 8254
    742   //
    743   // Setting 8254
    744   // Program timer 1 as refresh timer
    745   //
    746   IoWrite8 (0x43, 0x54);
    747   IoWrite8 (0x41, 0x12);
    748 
    749   //
    750   // RTC power failure handling
    751   //
    752   RtcPowerFailureHandler (PeiServices);
    753 
    754 
    755   PchMmPci32( 0, 0, 2, 0, 0x50) = 0x210;
    756 
    757   VariableSize = sizeof (SYSTEM_CONFIGURATION);
    758   ZeroMem (&SystemConfiguration, VariableSize);
    759 
    760   //
    761   // Obtain variable services
    762   //
    763   Status = (*PeiServices)->LocatePpi(
    764                              PeiServices,
    765                              &gEfiPeiReadOnlyVariable2PpiGuid,
    766                              0,
    767                              NULL,
    768                              (void **)&Variable
    769                              );
    770   ASSERT_EFI_ERROR(Status);
    771   Status = Variable->GetVariable (
    772                        Variable,
    773                        L"Setup",
    774                        &gEfiSetupVariableGuid,
    775                        NULL,
    776                        &VariableSize,
    777                        &SystemConfiguration
    778 					   );
    779   if (EFI_ERROR (Status) || VariableSize != sizeof(SYSTEM_CONFIGURATION)) {
    780     //The setup variable is corrupted
    781     VariableSize = sizeof(SYSTEM_CONFIGURATION);
    782     Status = Variable->GetVariable(
    783               Variable,
    784               L"SetupRecovery",
    785               &gEfiSetupVariableGuid,
    786               NULL,
    787               &VariableSize,
    788               &SystemConfiguration
    789               );
    790     ASSERT_EFI_ERROR (Status);
    791   }
    792 
    793   if (EFI_ERROR (Status)) {
    794     GGC = ((2 << 3) | 0x200);
    795     PciCfg16Write(EC_BASE, 0, 2, 0, 0x50, GGC);
    796     GGC = PciCfg16Read(EC_BASE, 0, 2, 0, 0x50);
    797     DEBUG((EFI_D_INFO , "GGC: 0x%08x GMSsize:0x%08x\n", GGC, (GGC & (BIT7|BIT6|BIT5|BIT4|BIT3))>>3));
    798   } else {
    799     if (SystemConfiguration.Igd == 1 && SystemConfiguration.PrimaryVideoAdaptor != 2) {
    800       GGC = (SystemConfiguration.IgdDvmt50PreAlloc << 3) |
    801             (SystemConfiguration.GTTSize == GTT_SIZE_1MB ? 0x100: 0x200);
    802       PciCfg16Write(EC_BASE, 0, 2, 0, 0x50, GGC);
    803       GGC = PciCfg16Read(EC_BASE, 0, 2, 0, 0x50);
    804       DEBUG((EFI_D_INFO , "GGC: 0x%08x GMSsize:0x%08x\n", GGC, (GGC & (BIT7|BIT6|BIT5|BIT4|BIT3))>>3));
    805     }
    806   }
    807 
    808   //
    809   // Initialize PlatformInfo HOB
    810   //
    811   Status = ReadPlatformIds(PeiServices, &PlatformInfo);
    812   ASSERT_EFI_ERROR (Status);
    813 
    814   //
    815   // 0 -> Disable , 1 -> Enable
    816   //
    817   if(SystemConfiguration.CfioPnpSettings == 1) {
    818     DEBUG((EFI_D_INFO, "CheckCfioPnpSettings: CFIO Pnp Settings Enabled\n"));
    819     PlatformInfo.CfioEnabled = 1;
    820   } else {
    821     DEBUG((EFI_D_INFO, "CheckCfioPnpSettings: CFIO Pnp Settings Disabled\n"));
    822     PlatformInfo.CfioEnabled = 0;
    823   }
    824 
    825   //
    826   // Build HOB for PlatformInfo
    827   //
    828   BuildGuidDataHob (
    829     &gEfiPlatformInfoGuid,
    830     &PlatformInfo,
    831     sizeof (EFI_PLATFORM_INFO_HOB)
    832     );
    833 
    834 
    835 #ifdef FTPM_ENABLE
    836   Status = FtpmPolicyInit(PeiServices, &SystemConfiguration);
    837   if (EFI_ERROR (Status)) {
    838     DEBUG((EFI_D_ERROR, "fTPM init failed.\n"));
    839   }
    840 #endif
    841 
    842 
    843   //
    844   // Set the new boot mode for MRC
    845   //
    846 #ifdef NOCS_S3_SUPPORT
    847   Status = UpdateBootMode (PeiServices);
    848   ASSERT_EFI_ERROR (Status);
    849 #endif
    850 
    851   DEBUG((EFI_D_INFO, "Setup MMIO size ... \n\n"));
    852 
    853   //
    854   // Setup MMIO size
    855   //
    856   Status = (*PeiServices)->AllocatePool(
    857                              PeiServices,
    858                              sizeof (EFI_PEI_PPI_DESCRIPTOR),
    859                              (void **)&mVlvMmioPolicyPpiDesc
    860                              );
    861   ASSERT_EFI_ERROR (Status);
    862   Status = (*PeiServices)->AllocatePool(
    863                              PeiServices,
    864                              sizeof (VLV_MMIO_POLICY_PPI),
    865                              (void **)&mVlvMmioPolicyPpi
    866                              );
    867   ASSERT_EFI_ERROR (Status);
    868   (*PeiServices)->SetMem (
    869                     (VOID *)mVlvMmioPolicyPpi,
    870                     sizeof (VLV_MMIO_POLICY_PPI),
    871                     0
    872                     );
    873   mVlvMmioPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
    874   mVlvMmioPolicyPpiDesc->Guid = &gVlvMmioPolicyPpiGuid;
    875   mVlvMmioPolicyPpiDesc->Ppi = mVlvMmioPolicyPpi;
    876   switch (SystemConfiguration.MmioSize) {
    877     case 0:      // 768MB
    878       mVlvMmioPolicyPpi->MmioSize = 0x300;
    879       break;
    880     case 1:      // 1GB
    881       mVlvMmioPolicyPpi->MmioSize = 0x400;
    882       break;
    883     case 2:      // 1.25GB
    884       mVlvMmioPolicyPpi->MmioSize = 0x500;
    885       break;
    886     case 3:      // 1.5GB
    887       mVlvMmioPolicyPpi->MmioSize = 0x600;
    888       break;
    889     case 4:      // 2GB
    890       mVlvMmioPolicyPpi->MmioSize = 0x800;
    891       break;
    892     default:
    893       mVlvMmioPolicyPpi->MmioSize = 0x800;
    894       break;
    895   }
    896   Status = (*PeiServices)->InstallPpi(
    897                              PeiServices,
    898                              mVlvMmioPolicyPpiDesc
    899                              );
    900   ASSERT_EFI_ERROR (Status);
    901 
    902   return Status;
    903 }
    904 
    905 EFI_STATUS
    906 ReadPlatformIds (
    907   IN CONST EFI_PEI_SERVICES             **PeiServices,
    908   IN OUT EFI_PLATFORM_INFO_HOB          *PlatformInfoHob
    909   )
    910 {
    911   {
    912     EFI_STATUS                      Status = EFI_SUCCESS;
    913     UINT8                           FabId = 0;
    914     UINTN                           DataSize;
    915     EFI_PLATFORM_INFO_HOB           TmpHob;
    916     EFI_PEI_READ_ONLY_VARIABLE2_PPI *PeiVar;
    917     UINT32                          CompatibleBoard = 0;
    918 
    919     Status = (**PeiServices).LocatePpi (
    920                                PeiServices,
    921                                &gEfiPeiReadOnlyVariable2PpiGuid,
    922                                0,
    923                                NULL,
    924                                (void **)&PeiVar
    925                                );
    926     ASSERT_EFI_ERROR (Status);
    927 
    928     DataSize = sizeof (EFI_PLATFORM_INFO_HOB);
    929     Status = PeiVar->GetVariable (
    930                        PeiVar,
    931                        L"PlatformInfo",
    932                        &gEfiVlv2VariableGuid,
    933                        NULL,
    934                        &DataSize,
    935                        &TmpHob
    936 					   );
    937 
    938     if (Status == EFI_SUCCESS) {
    939       PlatformInfoHob->BoardId        = TmpHob.BoardId;
    940       PlatformInfoHob->MemCfgID       = TmpHob.MemCfgID;
    941       PlatformInfoHob->BoardRev       = TmpHob.BoardRev;
    942       PlatformInfoHob->PlatformFlavor = TmpHob.PlatformFlavor;
    943       return Status;
    944     }
    945 
    946     CompatibleBoard = DetermineTurbotBoard();
    947    if (1 == CompatibleBoard) {
    948      PlatformInfoHob->BoardId    = BOARD_ID_MINNOW2_TURBOT;
    949      DEBUG ((EFI_D_INFO,  "I'm MinnowBoard Turbot!\n"));
    950    } else {
    951      PlatformInfoHob->BoardId    = BOARD_ID_MINNOW2;
    952      DEBUG ((EFI_D_INFO,  "I'm MinnowBoard Max!\n"));
    953    }
    954 
    955 
    956     PlatformInfoHob->MemCfgID   = 0;
    957     PlatformInfoHob->BoardRev   = FabId + 1;	// FabId = 0 means FAB1 (BoardRev = 1), FabId = 1 means FAB2 (BoardRev = 2)...
    958     PlatformInfoHob->PlatformFlavor = FlavorMobile;
    959   }
    960 
    961   return EFI_SUCCESS;
    962 }
    963 
    964 //
    965 // Start::Alpine Valley platform
    966 //
    967 /**
    968   This routine reads SysCtl registers
    969 
    970   @param SmbusBase   SMBUS Base Address
    971   @param SlvAddr     Targeted Smbus Slave device address
    972   @param Operation   Which SMBus protocol will be used
    973   @param Offset      Offset of the register
    974   @param  Length     Number of bytes
    975   @param  Buffer     Buffer contains values read from registers
    976 
    977   @retval SUCCESS as passed
    978   @retval Others as failed
    979 
    980 **/
    981 EFI_STATUS
    982 PeiSmbusExec (
    983   UINT16 SmbusBase,
    984   UINT8 SlvAddr,
    985   UINT8 Operation,
    986   UINT8 Offset,
    987   UINT8 *Length,
    988   UINT8 *Buffer
    989   )
    990 {
    991   EFI_STATUS  Status=EFI_SUCCESS;
    992   UINT8       AuxcReg;
    993   UINT8       SmbusOperation = 0;
    994   UINT8       StsReg;
    995   UINT8       SlvAddrReg;
    996   UINT8       HostCmdReg;
    997   UINT8       BlockCount = 0;
    998   BOOLEAN     BufferTooSmall;
    999   UINT8       Index;
   1000   UINT8       *CallBuffer;
   1001   UINT8  	  RetryCount = BUS_TRIES;
   1002 
   1003   //
   1004   // MrcSmbusExec supports byte and block read.
   1005   // Only allow Byte or block access
   1006   //
   1007   if (!((*Length  == AV_SC_BYTE_LEN) || (*Length == AV_SC_BLOCK_LEN))) {
   1008     return EFI_INVALID_PARAMETER;
   1009   }
   1010 
   1011   //
   1012   // See if its ok to use the bus based upon INUSE_STS bit.
   1013   //
   1014   Status = AcquireBus (SmbusBase);
   1015   ASSERT_EFI_ERROR(Status);
   1016 
   1017   CallBuffer = Buffer;
   1018 
   1019   //
   1020   //SmbStatus Bits of interest
   1021   //[6] = IUS (In Use Status)
   1022   //[4] = FAIL
   1023   //[3] = BERR (Bus Error = transaction collision)
   1024   //[2] = DERR (Device Error = Illegal Command Field, Unclaimed Cycle, Host Device Timeout, CRC Error)
   1025   //[1] = INTR (Successful completion of last command)
   1026   //[0] = HOST BUSY
   1027   //
   1028   //
   1029   // This is the main operation loop.  If the operation results in a Smbus
   1030   // collision with another master on the bus, it attempts the requested
   1031   // transaction again at least BUS_TRIES attempts.
   1032   //
   1033   while (RetryCount--) {
   1034     //
   1035     // Operation Specifics (pre-execution)
   1036     //
   1037     Status          = EFI_SUCCESS;
   1038     SlvAddrReg      = SlvAddr;
   1039     HostCmdReg      = Offset;
   1040     AuxcReg         = 0;
   1041 
   1042 	switch (Operation) {
   1043 
   1044 	case SMBUS_WRITE_BYTE:
   1045     IoWrite8 (SmbusBase+R_PCH_SMBUS_HD0, CallBuffer[0]);
   1046 		SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA;
   1047 	break;
   1048 
   1049     case SMBUS_READ_BYTE:
   1050       SmbusOperation = V_PCH_SMBUS_SMB_CMD_BYTE_DATA;
   1051 	  	SlvAddrReg |= B_PCH_SMBUS_RW_SEL_READ;
   1052       if (*Length < 1) {
   1053         Status = EFI_INVALID_PARAMETER;
   1054       }
   1055       	*Length = 1;
   1056 	break;
   1057 
   1058     case SMBUS_WRITE_BLOCK:
   1059       SmbusOperation  = V_PCH_SMBUS_SMB_CMD_BLOCK;
   1060       IoWrite8 (SmbusBase+R_PCH_SMBUS_HD0, *(UINT8 *) Length);
   1061      	BlockCount = (UINT8) (*Length);
   1062      	if ((*Length < 1) || (*Length > 32)) {
   1063         Status = EFI_INVALID_PARAMETER;
   1064         break;
   1065     	}
   1066       	AuxcReg |= B_PCH_SMBUS_E32B;
   1067 	break;
   1068 
   1069     case SMBUS_READ_BLOCK:
   1070       SmbusOperation = V_PCH_SMBUS_SMB_CMD_BLOCK;
   1071      	SlvAddrReg |= B_PCH_SMBUS_RW_SEL_READ;
   1072      	if ((*Length < 1) || (*Length > 32)) {
   1073         Status = EFI_INVALID_PARAMETER;
   1074         break;
   1075      	}
   1076       	AuxcReg |= B_PCH_SMBUS_E32B;
   1077 	break;
   1078 
   1079     default:
   1080       	Status = EFI_INVALID_PARAMETER;
   1081 	break;
   1082     }
   1083 
   1084     //
   1085     // Set Auxiliary Control register
   1086     //
   1087     IoWrite8 (SmbusBase+R_PCH_SMBUS_AUXC, AuxcReg);
   1088 
   1089     //
   1090     // Reset the pointer of the internal buffer
   1091     //
   1092     IoRead8 (SmbusBase+R_PCH_SMBUS_HCTL);
   1093 
   1094     //
   1095     // Now that the 32 byte buffer is turned on, we can write th block data
   1096     // into it
   1097     //
   1098     if (Operation == SMBUS_WRITE_BLOCK) {
   1099       for (Index = 0; Index < BlockCount; Index++) {
   1100         //
   1101         // Write next byte
   1102         //
   1103         IoWrite8 (SmbusBase+R_PCH_SMBUS_HBD, CallBuffer[Index]);
   1104       }
   1105     }
   1106 
   1107     //
   1108     // Set SMBus slave address for the device to read
   1109     //
   1110     IoWrite8(SmbusBase+R_PCH_SMBUS_TSA, SlvAddrReg);
   1111 
   1112     //
   1113     //
   1114     // Set Command register for the offset to read
   1115     //
   1116     IoWrite8(SmbusBase+R_PCH_SMBUS_HCMD, HostCmdReg );
   1117 
   1118     //
   1119     // Set Control Register to Set "operation command" protocol and start bit
   1120     //
   1121     IoWrite8(SmbusBase+R_PCH_SMBUS_HCTL, (UINT8) (SmbusOperation + B_PCH_SMBUS_START));
   1122 
   1123     //
   1124     // Wait for IO to complete
   1125     //
   1126 	do { StsReg = (UINT8) IoRead8(SmbusBase+0); } while ((StsReg & (BIT4|BIT3|BIT2|BIT1)) == 0);
   1127 
   1128 	  if (StsReg & B_PCH_SMBUS_DERR) {
   1129       Status = EFI_DEVICE_ERROR;
   1130       break;
   1131     } else if (StsReg & B_PCH_SMBUS_BERR) {
   1132       //
   1133       // Clear the Bus Error for another try
   1134       //
   1135       Status = EFI_DEVICE_ERROR;
   1136       IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
   1137 
   1138       //
   1139       // Clear Status Registers
   1140       //
   1141       IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
   1142       IoWrite8(SmbusBase+R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
   1143 
   1144       continue;
   1145     }
   1146 
   1147     //
   1148     // successfull completion
   1149     // Operation Specifics (post-execution)
   1150     //
   1151     switch (Operation) {
   1152 
   1153     case SMBUS_READ_BYTE:
   1154       CallBuffer[0] = (UINT8)(IoRead8 (SmbusBase+R_PCH_SMBUS_HD0));
   1155       break;
   1156 
   1157     case SMBUS_WRITE_BLOCK:
   1158       IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BYTE_DONE_STS);
   1159       break;
   1160 
   1161     case SMBUS_READ_BLOCK:
   1162       BufferTooSmall = FALSE;
   1163 
   1164       //
   1165       // Find out how many bytes will be in the block
   1166       //
   1167       BlockCount = (UINT8)(IoRead8 (SmbusBase+R_PCH_SMBUS_HD0));
   1168       if (*Length < BlockCount) {
   1169         BufferTooSmall = TRUE;
   1170       } else {
   1171         for (Index = 0; Index < BlockCount; Index++) {
   1172           //
   1173           // Read the byte
   1174           //
   1175           CallBuffer[Index] = (UINT8)IoRead8 (SmbusBase+R_PCH_SMBUS_HBD);
   1176         }
   1177       }
   1178 
   1179       *Length = BlockCount;
   1180       if (BufferTooSmall) {
   1181         Status = EFI_BUFFER_TOO_SMALL;
   1182       }
   1183       break;
   1184 
   1185     default:
   1186       break;
   1187     };
   1188 
   1189     if ((StsReg & B_PCH_SMBUS_BERR) && (Status == EFI_SUCCESS)) {
   1190       //
   1191       // Clear the Bus Error for another try
   1192       //
   1193       Status = EFI_DEVICE_ERROR;
   1194       IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_BERR);
   1195 
   1196       continue;
   1197     } else {
   1198       break;
   1199     }
   1200   }
   1201 
   1202   //
   1203   // Clear Status Registers and exit
   1204   //
   1205   IoWrite8(SmbusBase+R_PCH_SMBUS_HSTS, B_PCH_SMBUS_HSTS_ALL);
   1206   IoWrite8(SmbusBase+R_PCH_SMBUS_AUXS, B_PCH_SMBUS_CRCE);
   1207   IoWrite8(SmbusBase+R_PCH_SMBUS_AUXC, 0);
   1208   return Status;
   1209 }
   1210 //
   1211 // End::Alpine Valley platform
   1212 //
   1213 
   1214