]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkNorthCluster/Smm/Dxe/SmmControlDxe/SmmControlDriver.c
QuarkSocPkg: SmmControlDxe: remove set but unused variables
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Smm / Dxe / SmmControlDxe / SmmControlDriver.c
1 /** @file
2 This module produces the SMM COntrol2 Protocol for QNC
3
4 Copyright (c) 2013-2015 Intel Corporation.
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include <PiDxe.h>
17 #include <Protocol/SmmControl2.h>
18 #include <IndustryStandard/Pci.h>
19 #include <Library/DebugLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/UefiRuntimeServicesTableLib.h>
22 #include <Library/PcdLib.h>
23 #include <Library/IoLib.h>
24 #include <Library/PciLib.h>
25 #include <IntelQNCDxe.h>
26 #include <Library/QNCAccessLib.h>
27 #include <Uefi/UefiBaseType.h>
28
29 #define EFI_INTERNAL_POINTER 0x00000004
30
31 extern EFI_GUID gEfiEventVirtualAddressChangeGuid;
32
33 /**
34 Generates an SMI using the parameters passed in.
35
36 @param This A pointer to an instance of
37 EFI_SMM_CONTROL2_PROTOCOL
38 @param ArgumentBuffer The argument buffer
39 @param ArgumentBufferSize The size of the argument buffer
40 @param Periodic TRUE to indicate a periodical SMI
41 @param ActivationInterval Interval of the periodical SMI
42
43 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
44 @return Return value from SmmTrigger().
45
46 **/
47 EFI_STATUS
48 EFIAPI
49 Activate (
50 IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
51 IN OUT UINT8 *CommandPort OPTIONAL,
52 IN OUT UINT8 *DataPort OPTIONAL,
53 IN BOOLEAN Periodic OPTIONAL,
54 IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
55 );
56
57 /**
58 Clears an SMI.
59
60 @param This Pointer to an instance of EFI_SMM_CONTROL2_PROTOCOL
61 @param Periodic TRUE to indicate a periodical SMI
62
63 @return Return value from SmmClear()
64
65 **/
66 EFI_STATUS
67 EFIAPI
68 Deactivate (
69 IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
70 IN BOOLEAN Periodic OPTIONAL
71 );
72
73 ///
74 /// Handle for the SMM Control2 Protocol
75 ///
76 EFI_HANDLE mSmmControl2Handle = NULL;
77
78 ///
79 /// SMM COntrol2 Protocol instance
80 ///
81 EFI_SMM_CONTROL2_PROTOCOL mSmmControl2 = {
82 Activate,
83 Deactivate,
84 0
85 };
86
87 VOID
88 EFIAPI
89 SmmControlVirtualddressChangeEvent (
90 IN EFI_EVENT Event,
91 IN VOID *Context
92 )
93 /*++
94
95 Routine Description:
96
97 Fixup internal data pointers so that the services can be called in virtual mode.
98
99 Arguments:
100
101 Event The event registered.
102 Context Event context.
103
104 Returns:
105
106 None.
107
108 --*/
109 {
110 gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl2.Trigger));
111 gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSmmControl2.Clear));
112 }
113
114 /**
115 Clear SMI related chipset status and re-enable SMI by setting the EOS bit.
116
117 @retval EFI_SUCCESS The requested operation has been carried out successfully
118 @retval EFI_DEVICE_ERROR The EOS bit could not be set.
119
120 **/
121 EFI_STATUS
122 SmmClear (
123 VOID
124 )
125 {
126 UINT16 GPE0BLK_Base;
127
128 //
129 // Get GPE0BLK_Base
130 //
131 GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
132
133 //
134 // Clear the Power Button Override Status Bit, it gates EOS from being set.
135 // In QuarkNcSocId - Bit is read only. Handled by external SMC, do nothing.
136 //
137
138 //
139 // Clear the APM SMI Status Bit
140 //
141 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);
142
143 //
144 // Set the EOS Bit
145 //
146 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
147
148 return EFI_SUCCESS;
149 }
150
151 /**
152 Generates an SMI using the parameters passed in.
153
154 @param This A pointer to an instance of
155 EFI_SMM_CONTROL_PROTOCOL
156 @param ArgumentBuffer The argument buffer
157 @param ArgumentBufferSize The size of the argument buffer
158 @param Periodic TRUE to indicate a periodical SMI
159 @param ActivationInterval Interval of the periodical SMI
160
161 @retval EFI_INVALID_PARAMETER Periodic is TRUE or ArgumentBufferSize > 1
162 @retval EFI_SUCCESS SMI generated
163
164 **/
165 EFI_STATUS
166 EFIAPI
167 Activate (
168 IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
169 IN OUT UINT8 *CommandPort OPTIONAL,
170 IN OUT UINT8 *DataPort OPTIONAL,
171 IN BOOLEAN Periodic OPTIONAL,
172 IN EFI_SMM_PERIOD ActivationInterval OPTIONAL
173 )
174 {
175 UINT16 GPE0BLK_Base;
176 UINT32 NewValue;
177
178 //
179 // Get GPE0BLK_Base
180 //
181 GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
182
183 if (Periodic) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 //
188 // Clear any pending the APM SMI
189 //
190 if (EFI_ERROR (SmmClear())) {
191 return EFI_DEVICE_ERROR;
192 }
193
194 //
195 // Enable the APMC SMI
196 //
197 IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIE, B_QNC_GPE0BLK_SMIE_APM);
198
199 //
200 // Enable SMI globally
201 //
202 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
203 NewValue |= SMI_EN;
204 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
205
206
207 //
208 // Set APMC_STS
209 //
210 if (DataPort == NULL) {
211 IoWrite8 (PcdGet16 (PcdSmmDataPort), 0xFF);
212 } else {
213 IoWrite8 (PcdGet16 (PcdSmmDataPort), *DataPort);
214 }
215
216 //
217 // Generate the APMC SMI
218 //
219 if (CommandPort == NULL) {
220 IoWrite8 (PcdGet16 (PcdSmmActivationPort), 0xFF);
221 } else {
222 IoWrite8 (PcdGet16 (PcdSmmActivationPort), *CommandPort);
223 }
224
225 return EFI_SUCCESS;
226 }
227
228 /**
229 Clears an SMI.
230
231 @param This Pointer to an instance of EFI_SMM_CONTROL_PROTOCOL
232 @param Periodic TRUE to indicate a periodical SMI
233
234 @return Return value from SmmClear()
235
236 **/
237 EFI_STATUS
238 EFIAPI
239 Deactivate (
240 IN CONST EFI_SMM_CONTROL2_PROTOCOL *This,
241 IN BOOLEAN Periodic
242 )
243 {
244 if (Periodic) {
245 return EFI_INVALID_PARAMETER;
246 }
247
248 return SmmClear();
249 }
250
251 /**
252 This is the constructor for the SMM Control protocol.
253
254 This function installs EFI_SMM_CONTROL2_PROTOCOL.
255
256 @param ImageHandle Handle for the image of this driver
257 @param SystemTable Pointer to the EFI System Table
258
259 @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
260 @return The status returned from InstallProtocolInterface().
261
262 --*/
263 EFI_STATUS
264 SmmControl2Init (
265 IN EFI_HANDLE ImageHandle,
266 IN EFI_SYSTEM_TABLE *SystemTable
267 )
268 {
269 EFI_STATUS Status;
270 EFI_EVENT Event;
271 UINT16 PM1BLK_Base;
272 UINT16 GPE0BLK_Base;
273 BOOLEAN SciEn;
274 UINT32 NewValue;
275
276 //
277 // Get PM1BLK_Base & GPE0BLK_Base
278 //
279 PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);
280 GPE0BLK_Base = PcdGet16 (PcdGpe0blkIoBaseAddress);
281
282 //
283 // Install our protocol interfaces on the device's handle
284 //
285 Status = gBS->InstallMultipleProtocolInterfaces (
286 &mSmmControl2Handle,
287 &gEfiSmmControl2ProtocolGuid, &mSmmControl2,
288 NULL
289 );
290 ASSERT_EFI_ERROR (Status);
291
292 //
293 // Determine whether an ACPI OS is present (via the SCI_EN bit)
294 //
295 SciEn = (BOOLEAN)((IoRead16 (PM1BLK_Base + R_QNC_PM1BLK_PM1C) & B_QNC_PM1BLK_PM1C_SCIEN) != 0);
296 if (!SciEn) {
297 //
298 // Clear any SMIs that double as SCIs (when SCI_EN==0)
299 //
300 IoWrite16 ((PM1BLK_Base + R_QNC_PM1BLK_PM1S), B_QNC_PM1BLK_PM1S_ALL);
301 IoWrite16 ((PM1BLK_Base + R_QNC_PM1BLK_PM1E), 0x00000000);
302 IoWrite32 ((PM1BLK_Base + R_QNC_PM1BLK_PM1C), 0x00000000);
303 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_GPE0S), B_QNC_GPE0BLK_GPE0S_ALL);
304 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_GPE0E), 0x00000000);
305 }
306
307 //
308 // Clear and disable all SMIs that are unaffected by SCI_EN
309 // Set EOS
310 //
311 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), 0x00000000);
312 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), (B_QNC_GPE0BLK_SMIS_EOS + B_QNC_GPE0BLK_SMIS_ALL));
313
314 //
315 // Enable SMI globally
316 //
317 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
318 NewValue |= SMI_EN;
319 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
320
321 //
322 // Make sure to write this register last -- EOS re-enables SMIs for the QNC
323 //
324 IoAndThenOr32 (
325 GPE0BLK_Base + R_QNC_GPE0BLK_SMIE,
326 (UINT32)(~B_QNC_GPE0BLK_SMIE_ALL),
327 B_QNC_GPE0BLK_SMIE_APM
328 );
329
330 //
331 // Make sure EOS bit cleared
332 //
333 DEBUG_CODE_BEGIN ();
334 if (IoRead32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS) & B_QNC_GPE0BLK_SMIS_EOS) {
335 DEBUG ((
336 EFI_D_ERROR,
337 "******************************************************************************\n"
338 "BIG ERROR: SmmControl constructor couldn't properly initialize the ACPI table.\n"
339 " SmmControl->Clear will probably hang. \n"
340 " NOTE: SCI_EN = %d \n"
341 "******************************************************************************\n",
342 SciEn
343 ));
344
345 //
346 // If we want the system to stop, then keep the ASSERT(FALSE).
347 // Otherwise, comment it out.
348 //
349 ASSERT (FALSE);
350 }
351 DEBUG_CODE_END ();
352
353 Status = gBS->CreateEventEx (
354 EVT_NOTIFY_SIGNAL,
355 TPL_NOTIFY,
356 SmmControlVirtualddressChangeEvent,
357 NULL,
358 &gEfiEventVirtualAddressChangeGuid,
359 &Event
360 );
361 ASSERT_EFI_ERROR (Status);
362
363 return Status;
364 }