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