--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
+ \r\r
+ This program and the accompanying materials are licensed and made available under\r\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r\r
+ The full text of the license may be found at \r\r
+ http://opensource.org/licenses/bsd-license.php. \r\r
+ \r\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r\r
+ \r\r
+\r
+\r
+Module Name:\r
+\r
+ Stall.c\r
+\r
+Abstract:\r
+\r
+ Produce Stall Ppi.\r
+\r
+--*/\r
+\r
+\r
+#include "CommonHeader.h"\r
+#include "PlatformBaseAddresses.h"\r
+#include "PchRegs.h"\r
+\r
+/**\r
+ Waits for at least the given number of microseconds.\r
+\r
+ @param PeiServices General purpose services available to every PEIM.\r
+ @param This PPI instance structure.\r
+ @param Microseconds Desired length of time to wait.\r
+\r
+ @retval EFI_SUCCESS If the desired amount of time was passed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Stall (\r
+ IN CONST EFI_PEI_SERVICES **PeiServices,\r
+ IN CONST EFI_PEI_STALL_PPI *This,\r
+ IN UINTN Microseconds\r
+ )\r
+{\r
+ UINTN Ticks;\r
+ UINTN Counts;\r
+ UINT32 CurrentTick;\r
+ UINT32 OriginalTick;\r
+ UINT32 RemainingTick;\r
+\r
+ if (Microseconds == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OriginalTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR);\r
+ OriginalTick &= (V_PCH_ACPI_PM1_TMR_MAX_VAL - 1);\r
+ CurrentTick = OriginalTick;\r
+\r
+ //\r
+ // The timer frequency is 3.579545MHz, so 1 ms corresponds to 3.58 clocks\r
+ //\r
+ Ticks = Microseconds * 358 / 100 + OriginalTick + 1;\r
+\r
+ //\r
+ // The loops needed for timer overflow\r
+ //\r
+ Counts = (UINTN)RShiftU64((UINT64)Ticks, 24);\r
+\r
+ //\r
+ // Remaining clocks within one loop\r
+ //\r
+ RemainingTick = Ticks & 0xFFFFFF;\r
+\r
+ //\r
+ // Do not intend to use TMROF_STS bit of register PM1_STS, because this add extra\r
+ // one I/O operation, and may generate SMI\r
+ //\r
+ while (Counts != 0) {\r
+ CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL;\r
+ if (CurrentTick <= OriginalTick) {\r
+ Counts--;\r
+ }\r
+ OriginalTick = CurrentTick;\r
+ }\r
+\r
+ while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) {\r
+ OriginalTick = CurrentTick;\r
+ CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r