1 /** @file
2 
3   Copyright (c) 2004  - 2014, Intel Corporation. All rights reserved.<BR>
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
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 
DetermineTurbotBoard(void)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 
AcquireBus(UINT16 SmbusBase)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.
MfgMemoryTest(IN CONST EFI_PEI_SERVICES ** PeiServices,IN PEI_MFG_MEMORY_TEST_PPI * This,IN UINT32 BeginAddress,IN UINT32 MemoryLength)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;
RtcPowerFailureHandler(IN CONST EFI_PEI_SERVICES ** PeiServices)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);
PchBaseInit(VOID)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 /**
PeiInitPlatform(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)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
PeiSmbusExec(UINT16 SmbusBase,UINT8 SlvAddr,UINT8 Operation,UINT8 Offset,UINT8 * Length,UINT8 * Buffer)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