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 Module Name: 24 25 26 IchTcoReset.c 27 28 Abstract: 29 Implements the programming of events in TCO Reset 30 31 32 --*/ 33 34 #include "PlatformDxe.h" 35 #include <Protocol/TcoReset.h> 36 #include <Protocol/HwWatchdogTimer.h> 37 38 39 EFI_STATUS 40 EFIAPI 41 EnableTcoReset ( 42 IN UINT32 *RcrbGcsSaveValue 43 ); 44 45 EFI_STATUS 46 EFIAPI 47 DisableTcoReset ( 48 OUT UINT32 RcrbGcsRestoreValue 49 ); 50 51 EFI_TCO_RESET_PROTOCOL mTcoResetProtocol = { 52 EnableTcoReset, 53 DisableTcoReset 54 }; 55 56 /** 57 58 Enables the TCO timer to reset the system in case of a system hang. This is 59 used when writing the clock registers. 60 EnableTcoReset(IN UINT32 * RcrbGcsSaveValue)61 @param RcrbGcsSaveValue This is the value of the RCRB GCS register before it is 62 changed by this procedure. This will be used to restore 63 the settings of this register in PpiDisableTcoReset. 64 65 @retval EFI_STATUS 66 67 **/ 68 EFI_STATUS 69 EFIAPI 70 EnableTcoReset ( 71 IN UINT32 *RcrbGcsSaveValue 72 ) 73 { 74 UINT16 TmpWord; 75 UINT16 AcpiBase; 76 EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL *WatchdogTimerProtocol; 77 EFI_STATUS Status; 78 UINTN PbtnDisableInterval = 4; //Default value 79 80 // 81 // Get Watchdog Timer protocol. 82 // 83 Status = gBS->LocateProtocol ( 84 &gEfiWatchdogTimerDriverProtocolGuid, 85 NULL, 86 (VOID **)&WatchdogTimerProtocol 87 ); 88 89 // 90 // If the protocol is present, shut off the Timer as we enter BDS 91 // 92 if (!EFI_ERROR(Status)) { 93 WatchdogTimerProtocol->RestartWatchdogTimer(); 94 WatchdogTimerProtocol->AllowKnownReset(TRUE); 95 } 96 97 if (*RcrbGcsSaveValue == 0) { 98 PbtnDisableInterval = PcdGet32(PcdPBTNDisableInterval); 99 } else { 100 PbtnDisableInterval = *RcrbGcsSaveValue * 10 / 6; 101 } 102 103 // 104 // Read ACPI Base Address 105 // 106 AcpiBase = PchLpcPciCfg16(R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; 107 108 // 109 // Stop TCO if not already stopped 110 // 111 TmpWord = IoRead16(AcpiBase + R_PCH_TCO_CNT); 112 TmpWord |= B_PCH_TCO_CNT_TMR_HLT; 113 IoWrite16(AcpiBase + R_PCH_TCO_CNT, TmpWord); 114 115 // 116 // Clear second TCO status 117 // 118 IoWrite32(AcpiBase + R_PCH_TCO_STS, B_PCH_TCO_STS_SECOND_TO); 119 120 // 121 // Enable reboot on TCO timeout 122 // 123 *RcrbGcsSaveValue = MmioRead32 (PMC_BASE_ADDRESS + R_PCH_PMC_PM_CFG); 124 MmioAnd8 (PMC_BASE_ADDRESS + R_PCH_PMC_PM_CFG, (UINT8) ~B_PCH_PMC_PM_CFG_NO_REBOOT); 125 126 // 127 // Set TCO reload value (interval *.6s) 128 // 129 IoWrite32(AcpiBase + R_PCH_TCO_TMR, (UINT32)(PbtnDisableInterval<<16)); 130 131 // 132 // Force TCO to load new value 133 // 134 IoWrite8(AcpiBase + R_PCH_TCO_RLD, 4); 135 136 // 137 // Clear second TCO status 138 // 139 IoWrite32(AcpiBase + R_PCH_TCO_STS, B_PCH_TCO_STS_SECOND_TO); 140 141 // 142 // Start TCO timer running 143 // 144 TmpWord = IoRead16(AcpiBase + R_PCH_TCO_CNT); 145 TmpWord &= ~(B_PCH_TCO_CNT_TMR_HLT); 146 IoWrite16(AcpiBase + R_PCH_TCO_CNT, TmpWord); 147 148 return EFI_SUCCESS; 149 } 150 151 /** 152 Disables the TCO timer. This is used after writing the clock registers. DisableTcoReset(OUT UINT32 RcrbGcsRestoreValue)153 154 @param RcrbGcsRestoreValue Value saved in PpiEnableTcoReset so that it can 155 restored. 156 157 @retval EFI_STATUS 158 159 **/ 160 EFI_STATUS 161 EFIAPI 162 DisableTcoReset ( 163 OUT UINT32 RcrbGcsRestoreValue 164 ) 165 { 166 UINT16 TmpWord; 167 UINT16 AcpiBase; 168 EFI_WATCHDOG_TIMER_DRIVER_PROTOCOL *WatchdogTimerProtocol; 169 EFI_STATUS Status; 170 171 // 172 // Read ACPI Base Address 173 // 174 AcpiBase = PchLpcPciCfg16(R_PCH_LPC_ACPI_BASE) & B_PCH_LPC_ACPI_BASE_BAR; 175 176 // 177 // Stop the TCO timer 178 // 179 TmpWord = IoRead16(AcpiBase + R_PCH_TCO_CNT); 180 TmpWord |= B_PCH_TCO_CNT_TMR_HLT; 181 IoWrite16(AcpiBase + R_PCH_TCO_CNT, TmpWord); 182 183 // 184 // Get Watchdog Timer protocol. 185 // 186 Status = gBS->LocateProtocol ( 187 &gEfiWatchdogTimerDriverProtocolGuid, 188 NULL, 189 (VOID **)&WatchdogTimerProtocol 190 ); 191 192 // 193 // If the protocol is present, shut off the Timer as we enter BDS 194 // 195 if (!EFI_ERROR(Status)) { 196 WatchdogTimerProtocol->AllowKnownReset(FALSE); 197 } 198 199 return EFI_SUCCESS; 200 } InitTcoReset()201 202 /** 203 204 Updates the feature policies according to the setup variable. 205 206 @retval Returns VOID 207 208 **/ 209 VOID 210 InitTcoReset ( 211 ) 212 { 213 EFI_HANDLE Handle; 214 EFI_STATUS Status; 215 216 Handle = NULL; 217 Status = gBS->InstallProtocolInterface ( 218 &Handle, 219 &gEfiTcoResetProtocolGuid, 220 EFI_NATIVE_INTERFACE, 221 &mTcoResetProtocol 222 ); 223 ASSERT_EFI_ERROR(Status); 224 225 } 226