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