]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
QuarkSocPkg: Add new package for Quark SoC X1000
[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
41 UINT16 PM1BLK_Base;\r
42 UINT16 GPE0BLK_Base;\r
43 UINT32 NewValue;\r
44\r
45 //\r
46 // Get PM1BLK_Base & GPE0BLK_Base\r
47 //\r
48 PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);\r
49 GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);\r
50\r
51\r
52 //\r
53 // Enable APM SMI\r
54 //\r
55 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), B_QNC_GPE0BLK_SMIE_APM);\r
56\r
57 //\r
58 // Enable SMI globally\r
59 //\r
60 NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);\r
61 NewValue |= SMI_EN;\r
62 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);\r
63\r
64 //\r
65 // Set APM_STS\r
66 //\r
67 IoWrite8 (PcdGet16 (PcdSmmDataPort), Data);\r
68\r
69 //\r
70 // Generate the APM SMI\r
71 //\r
72 IoWrite8 (PcdGet16 (PcdSmmActivationPort), PcdGet8 (PcdSmmActivationData));\r
73\r
74 //\r
75 // Clear the APM SMI Status Bit\r
76 //\r
77 IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);\r
78\r
79 //\r
80 // Set the EOS Bit\r
81 //\r
82 IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);\r
83}\r
84\r
85\r
86/**\r
87 Triggers an SMI at boot time.\r
88\r
89 This function triggers a software SMM interrupt at boot time.\r
90\r
91**/\r
92VOID\r
93EFIAPI\r
94TriggerBootServiceSoftwareSmi (\r
95 VOID\r
96 )\r
97{\r
98 InternalTriggerSmi (BOOT_SERVICE_SOFTWARE_SMI_DATA);\r
99}\r
100\r
101\r
102/**\r
103 Triggers an SMI at run time.\r
104\r
105 This function triggers a software SMM interrupt at run time.\r
106\r
107**/\r
108VOID\r
109EFIAPI\r
110TriggerRuntimeSoftwareSmi (\r
111 VOID\r
112 )\r
113{\r
114 InternalTriggerSmi (RUNTIME_SOFTWARE_SMI_DATA);\r
115}\r
116\r
117\r
118/**\r
119 Gets the software SMI data.\r
120\r
121 This function tests if a software SMM interrupt happens. If a software SMI happens,\r
122 it retrieves the SMM data and returns it as a non-negative value; otherwise a negative\r
123 value is returned.\r
124\r
125 @return Data The data retrieved from SMM data port in case of a software SMI;\r
126 otherwise a negative value.\r
127\r
128**/\r
129INTN\r
130InternalGetSwSmiData (\r
131 VOID\r
132 )\r
133{\r
134 UINT8 SmiStatus;\r
135 UINT8 Data;\r
136\r
137 SmiStatus = IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);\r
138 if (((SmiStatus & B_QNC_GPE0BLK_SMIS_APM) != 0) &&\r
139 (IoRead8 (PcdGet16 (PcdSmmActivationPort)) == PcdGet8 (PcdSmmActivationData))) {\r
140 Data = IoRead8 (PcdGet16 (PcdSmmDataPort));\r
141 return (INTN)(UINTN)Data;\r
142 }\r
143\r
144 return -1;\r
145}\r
146\r
147\r
148/**\r
149 Test if a boot time software SMI happened.\r
150\r
151 This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and\r
152 it was triggered at boot time, it returns TRUE. Otherwise, it returns FALSE.\r
153\r
154 @retval TRUE A software SMI triggered at boot time happened.\r
155 @retval FLASE No software SMI happened or the software SMI was triggered at run time.\r
156\r
157**/\r
158BOOLEAN\r
159EFIAPI\r
160IsBootServiceSoftwareSmi (\r
161 VOID\r
162 )\r
163{\r
164 return (BOOLEAN) (InternalGetSwSmiData () == BOOT_SERVICE_SOFTWARE_SMI_DATA);\r
165}\r
166\r
167\r
168/**\r
169 Test if a run time software SMI happened.\r
170\r
171 This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and\r
172 it was triggered at run time, it returns TRUE. Otherwise, it returns FALSE.\r
173\r
174 @retval TRUE A software SMI triggered at run time happened.\r
175 @retval FLASE No software SMI happened or the software SMI was triggered at boot time.\r
176\r
177**/\r
178BOOLEAN\r
179EFIAPI\r
180IsRuntimeSoftwareSmi (\r
181 VOID\r
182 )\r
183{\r
184 return (BOOLEAN) (InternalGetSwSmiData () == RUNTIME_SOFTWARE_SMI_DATA);\r
185}\r
186\r
187\r
188\r
189/**\r
190\r
191 Clear APM SMI Status Bit; Set the EOS bit.\r
192\r
193**/\r
194VOID\r
195EFIAPI\r
196ClearSmi (\r
197 VOID\r
198 )\r
199{\r
200\r
201 UINT16 GPE0BLK_Base;\r
202\r
203 //\r
204 // Get GpeBase\r
205 //\r
206 GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);\r
207\r
208 //\r
209 // Clear the APM SMI Status Bit\r
210 //\r
211 IoOr16 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_APM);\r
212\r
213 //\r
214 // Set the EOS Bit\r
215 //\r
216 IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);\r
217}\r
218\r
219/**\r
220 This routine is the chipset code that accepts a request to "open" a region of SMRAM.\r
221 The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.\r
222 The use of "open" means that the memory is visible from all boot-service\r
223 and SMM agents.\r
224\r
225 @retval FALSE Cannot open a locked SMRAM region\r
226 @retval TRUE Success to open SMRAM region.\r
227**/\r
228BOOLEAN\r
229EFIAPI\r
230QNCOpenSmramRegion (\r
231 VOID\r
232 )\r
233{\r
234 UINT32 Smram;\r
235\r
236 // Read the SMRAM register\r
237 Smram = QncHsmmcRead ();\r
238\r
239 //\r
240 // Is the platform locked?\r
241 //\r
242 if (Smram & SMM_LOCKED) {\r
243 // Cannot Open a locked region\r
244 DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n"));\r
245 return FALSE;\r
246 }\r
247\r
248 //\r
249 // Open all SMRAM regions for Host access only\r
250 //\r
251 Smram |= (SMM_WRITE_OPEN | SMM_READ_OPEN); // Open for Host.\r
252 Smram &= ~(NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN); // Not for others.\r
253\r
254 //\r
255 // Write the SMRAM register\r
256 //\r
257 QncHsmmcWrite (Smram);\r
258\r
259 return TRUE;\r
260}\r
261\r
262/**\r
263 This routine is the chipset code that accepts a request to "close" a region of SMRAM.\r
264 The region could be legacy AB or TSEG near top of physical memory.\r
265 The use of "close" means that the memory is only visible from SMM agents,\r
266 not from BS or RT code.\r
267\r
268 @retval FALSE Cannot open a locked SMRAM region\r
269 @retval TRUE Success to open SMRAM region.\r
270**/\r
271BOOLEAN\r
272EFIAPI\r
273QNCCloseSmramRegion (\r
274 VOID\r
275 )\r
276{\r
277 UINT32 Smram;\r
278\r
279 // Read the SMRAM register.\r
280 Smram = QncHsmmcRead ();\r
281\r
282 //\r
283 // Is the platform locked?\r
284 //\r
285 if(Smram & SMM_LOCKED) {\r
286 // Cannot Open a locked region\r
287 DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n"));\r
288 return FALSE;\r
289 }\r
290\r
291 Smram &= (~(SMM_WRITE_OPEN | SMM_READ_OPEN | NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN));\r
292\r
293 QncHsmmcWrite (Smram);\r
294\r
295 return TRUE;\r
296}\r
297\r
298/**\r
299 This routine is the chipset code that accepts a request to "lock" SMRAM.\r
300 The region could be legacy AB or TSEG near top of physical memory.\r
301 The use of "lock" means that the memory can no longer be opened\r
302 to BS state.\r
303**/\r
304VOID\r
305EFIAPI\r
306QNCLockSmramRegion (\r
307 VOID\r
308 )\r
309{\r
310 UINT32 Smram;\r
311\r
312 // Read the SMRAM register.\r
313 Smram = QncHsmmcRead ();\r
314 if(Smram & SMM_LOCKED) {\r
315 DEBUG ((EFI_D_WARN, "SMRAM region already locked!\n"));\r
316 }\r
317 Smram |= SMM_LOCKED;\r
318\r
319 QncHsmmcWrite (Smram);\r
320\r
321 return;\r
322}\r