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