IchTcoReset.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /** @file
  2. Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. Module Name:
  5. IchTcoReset.c
  6. Abstract:
  7. Implements the programming of events in TCO Reset
  8. --*/
  9. #include "PlatformDxe.h"
  10. #include <Protocol/TcoReset.h>
  11. #include <Protocol/HwWatchdogTimer.h>
  12. EFI_STATUS
  13. EFIAPI
  14. EnableTcoReset (
  15. IN UINT32 *RcrbGcsSaveValue
  16. );
  17. EFI_STATUS
  18. EFIAPI
  19. DisableTcoReset (
  20. OUT UINT32 RcrbGcsRestoreValue
  21. );
  22. EFI_TCO_RESET_PROTOCOL mTcoResetProtocol = {
  23. EnableTcoReset,
  24. DisableTcoReset
  25. };
  26. /**
  27. Enables the TCO timer to reset the system in case of a system hang. This is
  28. used when writing the clock registers.
  29. @param RcrbGcsSaveValue This is the value of the RCRB GCS register before it is
  30. changed by this procedure. This will be used to restore
  31. the settings of this register in PpiDisableTcoReset.
  32. @retval EFI_STATUS
  33. **/
  34. EFI_STATUS
  35. EFIAPI
  36. EnableTcoReset (
  37. IN UINT32 *RcrbGcsSaveValue
  38. )
  39. {
  40. UINT16 TmpWord;
  41. UINT16 AcpiBase;
  42. EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL *WatchdogTimerProtocol;
  43. EFI_STATUS Status;
  44. UINTN PbtnDisableInterval = 4; //Default value
  45. //
  46. // Get Watchdog Timer protocol.
  47. //
  48. Status = gBS->LocateProtocol (
  49. &gEfiWatchdogTimerDriverProtocolGuid,
  50. NULL,
  51. (VOID **)&WatchdogTimerProtocol
  52. );
  53. //
  54. // If the protocol is present, shut off the Timer as we enter BDS
  55. //
  56. if (!EFI_ERROR(Status)) {
  57. WatchdogTimerProtocol->RestartWatchdogTimer();
  58. WatchdogTimerProtocol->AllowKnownReset(TRUE);
  59. }
  60. if (*RcrbGcsSaveValue == 0) {
  61. PbtnDisableInterval = PcdGet32(PcdPBTNDisableInterval);
  62. } else {
  63. PbtnDisableInterval = *RcrbGcsSaveValue * 10 / 6;
  64. }
  65. //
  66. // Read ACPI Base Address
  67. //
  68. AcpiBase = PchLpcPciCfg16(R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR;
  69. //
  70. // Stop TCO if not already stopped
  71. //
  72. TmpWord = IoRead16(AcpiBase + R_PCH_TCO_CNT);
  73. TmpWord |= B_PCH_TCO_CNT_TMR_HLT;
  74. IoWrite16(AcpiBase + R_PCH_TCO_CNT, TmpWord);
  75. //
  76. // Clear second TCO status
  77. //
  78. IoWrite32(AcpiBase + R_PCH_TCO_STS, B_PCH_TCO_STS_SECOND_TO);
  79. //
  80. // Enable reboot on TCO timeout
  81. //
  82. *RcrbGcsSaveValue = MmioRead32 (PMC_BASE_ADDRESS + R_PCH_PMC_PM_CFG);
  83. MmioAnd8 (PMC_BASE_ADDRESS + R_PCH_PMC_PM_CFG, (UINT8) ~B_PCH_PMC_PM_CFG_NO_REBOOT);
  84. //
  85. // Set TCO reload value (interval *.6s)
  86. //
  87. IoWrite32(AcpiBase + R_PCH_TCO_TMR, (UINT32)(PbtnDisableInterval<<16));
  88. //
  89. // Force TCO to load new value
  90. //
  91. IoWrite8(AcpiBase + R_PCH_TCO_RLD, 4);
  92. //
  93. // Clear second TCO status
  94. //
  95. IoWrite32(AcpiBase + R_PCH_TCO_STS, B_PCH_TCO_STS_SECOND_TO);
  96. //
  97. // Start TCO timer running
  98. //
  99. TmpWord = IoRead16(AcpiBase + R_PCH_TCO_CNT);
  100. TmpWord &= ~(B_PCH_TCO_CNT_TMR_HLT);
  101. IoWrite16(AcpiBase + R_PCH_TCO_CNT, TmpWord);
  102. return EFI_SUCCESS;
  103. }
  104. /**
  105. Disables the TCO timer. This is used after writing the clock registers.
  106. @param RcrbGcsRestoreValue Value saved in PpiEnableTcoReset so that it can
  107. restored.
  108. @retval EFI_STATUS
  109. **/
  110. EFI_STATUS
  111. EFIAPI
  112. DisableTcoReset (
  113. OUT UINT32 RcrbGcsRestoreValue
  114. )
  115. {
  116. UINT16 TmpWord;
  117. UINT16 AcpiBase;
  118. EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL *WatchdogTimerProtocol;
  119. EFI_STATUS Status;
  120. //
  121. // Read ACPI Base Address
  122. //
  123. AcpiBase = PchLpcPciCfg16(R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR;
  124. //
  125. // Stop the TCO timer
  126. //
  127. TmpWord = IoRead16(AcpiBase + R_PCH_TCO_CNT);
  128. TmpWord |= B_PCH_TCO_CNT_TMR_HLT;
  129. IoWrite16(AcpiBase + R_PCH_TCO_CNT, TmpWord);
  130. //
  131. // Get Watchdog Timer protocol.
  132. //
  133. Status = gBS->LocateProtocol (
  134. &gEfiWatchdogTimerDriverProtocolGuid,
  135. NULL,
  136. (VOID **)&WatchdogTimerProtocol
  137. );
  138. //
  139. // If the protocol is present, shut off the Timer as we enter BDS
  140. //
  141. if (!EFI_ERROR(Status)) {
  142. WatchdogTimerProtocol->AllowKnownReset(FALSE);
  143. }
  144. return EFI_SUCCESS;
  145. }
  146. /**
  147. Updates the feature policies according to the setup variable.
  148. @retval Returns VOID
  149. **/
  150. VOID
  151. InitTcoReset (
  152. )
  153. {
  154. EFI_HANDLE Handle;
  155. EFI_STATUS Status;
  156. Handle = NULL;
  157. Status = gBS->InstallProtocolInterface (
  158. &Handle,
  159. &gEfiTcoResetProtocolGuid,
  160. EFI_NATIVE_INTERFACE,
  161. &mTcoResetProtocol
  162. );
  163. ASSERT_EFI_ERROR(Status);
  164. }