13cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/*++ 23cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 33cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiCopyright (c) 1999 - 2014, Intel Corporation. All rights reserved 43cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 53cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 63cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei This program and the accompanying materials are licensed and made available under 73cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 83cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei the terms and conditions of the BSD License that accompanies this distribution. 93cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei The full text of the license may be found at 113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei http://opensource.org/licenses/bsd-license.php. 133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 243cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiModule Name: 253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei SmmIo.c 273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 283cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiAbstract: 293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei SMM I/O access utility implementation file, for Ia32 313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei--*/ 333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// 353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// Include files 363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei// 373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include "Library/StallSmmLib.h" 383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include "Pi/PiSmmCis.h" 393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include "PiDxe.h" 403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include <Library/IoLib.h> 413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include <Library/PcdLib.h> 423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include "PchAccess.h" 433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/** 453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei Delay for at least the request number of microseconds. 463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei Timer used is ACPI time counter, which has 1us granularity. 473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei @param Microseconds Number of microseconds to delay. 493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei @retval None 513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/ 533cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiVOID 543cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiSmmStall ( 553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei IN UINTN Microseconds 563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei ) 573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{ 583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei UINTN Ticks; 593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei UINTN Counts; 603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei UINTN CurrentTick; 613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei UINTN OriginalTick; 623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei UINTN RemainingTick; 633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei UINT16 AcpiBaseAddr; 643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei if (Microseconds == 0) { 663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei return; 673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei } 683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei AcpiBaseAddr = PchLpcPciCfg16 (R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; 703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei OriginalTick = IoRead32 (AcpiBaseAddr + R_PCH_ACPI_PM1_TMR); 723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei CurrentTick = OriginalTick; 733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // 753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks 763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // 773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei Ticks = Microseconds * 358 / 100 + OriginalTick + 1; 783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // 803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // The loops needed by timer overflow 813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // 823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei Counts = Ticks / V_PCH_ACPI_PM1_TMR_MAX_VAL; 833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // 853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // Remaining clocks within one loop 863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // 873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei RemainingTick = Ticks % V_PCH_ACPI_PM1_TMR_MAX_VAL; 883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei 893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // 903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // not intend to use TMROF_STS bit of register PM1_STS, because this adds extra 913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // one I/O operation, and maybe generate SMI 923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei // 933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei while ((Counts != 0) || (RemainingTick > CurrentTick)) { 943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei CurrentTick = IoRead32 (AcpiBaseAddr + R_PCH_ACPI_PM1_TMR); 95 // 96 // Check if timer overflow 97 // 98 if (CurrentTick < OriginalTick) { 99 Counts--; 100 } 101 OriginalTick = CurrentTick; 102 } 103} 104