]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
IntelFsp2WrapperPkg: Add a PCD to control if signaling PciEnumerationComplete.
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Library / QNCSmmLib / QNCSmmLib.c
CommitLineData
9b6bbcdb
MK
1/** @file\r
2QNC Smm Library Services that implements SMM Region access, S/W SMI generation and detection.\r
3\r
4Copyright (c) 2013-2015 Intel Corporation.\r
5\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16\r
17#include <Base.h>\r
18#include <IntelQNCRegs.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/PcdLib.h>\r
21#include <Library/IoLib.h>\r
22#include <Uefi/UefiBaseType.h>\r
23#include <Library/QNCAccessLib.h>\r
24\r
25#define BOOT_SERVICE_SOFTWARE_SMI_DATA 0\r
26#define RUNTIME_SOFTWARE_SMI_DATA 1\r
27\r
28/**\r
29 Triggers a run time or boot time SMI.\r
30\r
31 This function triggers a software SMM interrupt and set the APMC status with an 8-bit Data.\r
32\r
33 @param Data The value to set the APMC status.\r
34\r
35**/\r
36VOID\r
37InternalTriggerSmi (\r
38 IN UINT8 Data\r
39 )\r
40{\r
9b6bbcdb
MK
41 UINT16 GPE0BLK_Base;\r
42 UINT32 NewValue;\r
43\r
44 //\r
8f7c4375 45 // Get GPE0BLK_Base\r
9b6bbcdb 46 //\r
9b6bbcdb
MK
47 GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);\r
48\r
49\r
50 //\r
51 // Enable APM SMI\r
52 //\r
53 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), B_QNC_GPE0BLK_SMIE_APM);\r
54\r
55 //\r
56 // Enable SMI globally\r
57 //\r
58 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
59 NewValue |= SMI_EN;\r
60 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
61\r
62 //\r
63 // Set APM_STS\r
64 //\r
65 IoWrite8 (PcdGet16 (PcdSmmDataPort), Data);\r
66\r
67 //\r
68 // Generate the APM SMI\r
69 //\r
70 IoWrite8 (PcdGet16 (PcdSmmActivationPort), PcdGet8 (PcdSmmActivationData));\r
71\r
72 //\r
73 // Clear the APM SMI Status Bit\r
74 //\r
75 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);\r
76\r
77 //\r
78 // Set the EOS Bit\r
79 //\r
80 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);\r
81}\r
82\r
83\r
84/**\r
85 Triggers an SMI at boot time.\r
86\r
87 This function triggers a software SMM interrupt at boot time.\r
88\r
89**/\r
90VOID\r
91EFIAPI\r
92TriggerBootServiceSoftwareSmi (\r
93 VOID\r
94 )\r
95{\r
96 InternalTriggerSmi (BOOT_SERVICE_SOFTWARE_SMI_DATA);\r
97}\r
98\r
99\r
100/**\r
101 Triggers an SMI at run time.\r
102\r
103 This function triggers a software SMM interrupt at run time.\r
104\r
105**/\r
106VOID\r
107EFIAPI\r
108TriggerRuntimeSoftwareSmi (\r
109 VOID\r
110 )\r
111{\r
112 InternalTriggerSmi (RUNTIME_SOFTWARE_SMI_DATA);\r
113}\r
114\r
115\r
116/**\r
117 Gets the software SMI data.\r
118\r
119 This function tests if a software SMM interrupt happens. If a software SMI happens,\r
120 it retrieves the SMM data and returns it as a non-negative value; otherwise a negative\r
121 value is returned.\r
122\r
123 @return Data The data retrieved from SMM data port in case of a software SMI;\r
124 otherwise a negative value.\r
125\r
126**/\r
127INTN\r
128InternalGetSwSmiData (\r
129 VOID\r
130 )\r
131{\r
132 UINT8 SmiStatus;\r
133 UINT8 Data;\r
134\r
135 SmiStatus = IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);\r
136 if (((SmiStatus & B_QNC_GPE0BLK_SMIS_APM) != 0) &&\r
137 (IoRead8 (PcdGet16 (PcdSmmActivationPort)) == PcdGet8 (PcdSmmActivationData))) {\r
138 Data = IoRead8 (PcdGet16 (PcdSmmDataPort));\r
139 return (INTN)(UINTN)Data;\r
140 }\r
141\r
142 return -1;\r
143}\r
144\r
145\r
146/**\r
147 Test if a boot time software SMI happened.\r
148\r
149 This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and\r
150 it was triggered at boot time, it returns TRUE. Otherwise, it returns FALSE.\r
151\r
152 @retval TRUE A software SMI triggered at boot time happened.\r
153 @retval FLASE No software SMI happened or the software SMI was triggered at run time.\r
154\r
155**/\r
156BOOLEAN\r
157EFIAPI\r
158IsBootServiceSoftwareSmi (\r
159 VOID\r
160 )\r
161{\r
162 return (BOOLEAN) (InternalGetSwSmiData () == BOOT_SERVICE_SOFTWARE_SMI_DATA);\r
163}\r
164\r
165\r
166/**\r
167 Test if a run time software SMI happened.\r
168\r
169 This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and\r
170 it was triggered at run time, it returns TRUE. Otherwise, it returns FALSE.\r
171\r
172 @retval TRUE A software SMI triggered at run time happened.\r
173 @retval FLASE No software SMI happened or the software SMI was triggered at boot time.\r
174\r
175**/\r
176BOOLEAN\r
177EFIAPI\r
178IsRuntimeSoftwareSmi (\r
179 VOID\r
180 )\r
181{\r
182 return (BOOLEAN) (InternalGetSwSmiData () == RUNTIME_SOFTWARE_SMI_DATA);\r
183}\r
184\r
185\r
186\r
187/**\r
188\r
189 Clear APM SMI Status Bit; Set the EOS bit.\r
190\r
191**/\r
192VOID\r
193EFIAPI\r
194ClearSmi (\r
195 VOID\r
196 )\r
197{\r
198\r
199 UINT16 GPE0BLK_Base;\r
200\r
201 //\r
202 // Get GpeBase\r
203 //\r
204 GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);\r
205\r
206 //\r
207 // Clear the APM SMI Status Bit\r
208 //\r
209 IoOr16 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_APM);\r
210\r
211 //\r
212 // Set the EOS Bit\r
213 //\r
214 IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);\r
215}\r
216\r
217/**\r
218 This routine is the chipset code that accepts a request to "open" a region of SMRAM.\r
219 The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
220 The use of "open" means that the memory is visible from all boot-service\r
221 and SMM agents.\r
222\r
223 @retval FALSE Cannot open a locked SMRAM region\r
224 @retval TRUE Success to open SMRAM region.\r
225**/\r
226BOOLEAN\r
227EFIAPI\r
228QNCOpenSmramRegion (\r
229 VOID\r
230 )\r
231{\r
232 UINT32 Smram;\r
233\r
234 // Read the SMRAM register\r
235 Smram = QncHsmmcRead ();\r
236\r
237 //\r
238 // Is the platform locked?\r
239 //\r
240 if (Smram & SMM_LOCKED) {\r
241 // Cannot Open a locked region\r
242 DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n"));\r
243 return FALSE;\r
244 }\r
245\r
246 //\r
247 // Open all SMRAM regions for Host access only\r
248 //\r
249 Smram |= (SMM_WRITE_OPEN | SMM_READ_OPEN); // Open for Host.\r
250 Smram &= ~(NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN); // Not for others.\r
251\r
252 //\r
253 // Write the SMRAM register\r
254 //\r
255 QncHsmmcWrite (Smram);\r
256\r
257 return TRUE;\r
258}\r
259\r
260/**\r
261 This routine is the chipset code that accepts a request to "close" a region of SMRAM.\r
262 The region could be legacy AB or TSEG near top of physical memory.\r
263 The use of "close" means that the memory is only visible from SMM agents,\r
264 not from BS or RT code.\r
265\r
266 @retval FALSE Cannot open a locked SMRAM region\r
267 @retval TRUE Success to open SMRAM region.\r
268**/\r
269BOOLEAN\r
270EFIAPI\r
271QNCCloseSmramRegion (\r
272 VOID\r
273 )\r
274{\r
275 UINT32 Smram;\r
276\r
277 // Read the SMRAM register.\r
278 Smram = QncHsmmcRead ();\r
279\r
280 //\r
281 // Is the platform locked?\r
282 //\r
283 if(Smram & SMM_LOCKED) {\r
284 // Cannot Open a locked region\r
285 DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n"));\r
286 return FALSE;\r
287 }\r
288\r
289 Smram &= (~(SMM_WRITE_OPEN | SMM_READ_OPEN | NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN));\r
290\r
291 QncHsmmcWrite (Smram);\r
292\r
293 return TRUE;\r
294}\r
295\r
296/**\r
297 This routine is the chipset code that accepts a request to "lock" SMRAM.\r
298 The region could be legacy AB or TSEG near top of physical memory.\r
299 The use of "lock" means that the memory can no longer be opened\r
300 to BS state.\r
301**/\r
302VOID\r
303EFIAPI\r
304QNCLockSmramRegion (\r
305 VOID\r
306 )\r
307{\r
308 UINT32 Smram;\r
309\r
310 // Read the SMRAM register.\r
311 Smram = QncHsmmcRead ();\r
312 if(Smram & SMM_LOCKED) {\r
313 DEBUG ((EFI_D_WARN, "SMRAM region already locked!\n"));\r
314 }\r
315 Smram |= SMM_LOCKED;\r
316\r
317 QncHsmmcWrite (Smram);\r
318\r
319 return;\r
320}\r