]>
Commit | Line | Data |
---|---|---|
b303605e MK |
1 | /** @file\r |
2 | ACPISMM Driver implementation file.\r | |
3 | \r | |
4 | This is QNC Smm platform driver\r | |
5 | \r | |
6 | Copyright (c) 2013-2015 Intel Corporation.\r | |
7 | \r | |
8 | This program and the accompanying materials\r | |
9 | are licensed and made available under the terms and conditions of the BSD License\r | |
10 | which accompanies this distribution. The full text of the license may be found at\r | |
11 | http://opensource.org/licenses/bsd-license.php\r | |
12 | \r | |
13 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
14 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
15 | \r | |
16 | \r | |
17 | **/\r | |
18 | \r | |
19 | #include <AcpiSmmPlatform.h>\r | |
20 | \r | |
21 | #define PCILIB_TO_COMMON_ADDRESS(Address) \\r | |
22 | ((UINT64) ((((UINTN) ((Address>>20) & 0xff)) << 24) + (((UINTN) ((Address>>15) & 0x1f)) << 16) + (((UINTN) ((Address>>12) & 0x07)) << 8) + ((UINTN) (Address & 0xfff ))))\r | |
23 | \r | |
24 | //\r | |
25 | // Modular variables needed by this driver\r | |
26 | //\r | |
27 | EFI_ACPI_SMM_DEV mAcpiSmm;\r | |
28 | \r | |
29 | UINT8 mPciCfgRegTable[] = {\r | |
30 | //\r | |
31 | // Logic to decode the table masks to arrive at the registers saved\r | |
32 | // Dword Registers are saved. For a given mask, the Base+offset register\r | |
33 | // will be saved as in the table below.\r | |
34 | // (example) To save register 0x24, 0x28 the mask at the Base 0x20 will be 0x06\r | |
35 | // Base 0x00 0x20 0x40 0x60 0x80 0xA0 0xC0 0xE0\r | |
36 | // Mask offset\r | |
37 | // 0x01 0x00\r | |
38 | // 0x02 0x04\r | |
39 | // 0x04 0x08\r | |
40 | // 0x08 0x0C\r | |
41 | // 0x10 0x10\r | |
42 | // 0x20 0x14\r | |
43 | // 0x40 0x18\r | |
44 | // 0x80 0x1C\r | |
45 | //\r | |
46 | \r | |
47 | //\r | |
48 | // Bus, Dev, Func,\r | |
49 | // 00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF\r | |
50 | // Only Bus 0 device is supported now\r | |
51 | //\r | |
52 | \r | |
53 | //\r | |
54 | // Quark South Cluster devices\r | |
55 | //\r | |
56 | PCI_DEVICE (0, 20, 0),\r | |
57 | PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
58 | \r | |
59 | PCI_DEVICE (0, 20, 1),\r | |
60 | PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
61 | \r | |
62 | PCI_DEVICE (0, 20, 2),\r | |
63 | PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
64 | \r | |
65 | PCI_DEVICE (0, 20, 3),\r | |
66 | PCI_REG_MASK (0x18, 0x98, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00),\r | |
67 | \r | |
68 | PCI_DEVICE (0, 20, 4),\r | |
69 | PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
70 | \r | |
71 | PCI_DEVICE (0, 20, 5),\r | |
72 | PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
73 | \r | |
74 | PCI_DEVICE (0, 20, 6),\r | |
75 | PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
76 | \r | |
77 | PCI_DEVICE (0, 20, 7),\r | |
78 | PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
79 | \r | |
80 | PCI_DEVICE (0, 21, 0),\r | |
81 | PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
82 | \r | |
83 | PCI_DEVICE (0, 21, 1),\r | |
84 | PCI_REG_MASK (0x18, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
85 | \r | |
86 | PCI_DEVICE (0, 21, 2),\r | |
87 | PCI_REG_MASK (0x38, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
88 | \r | |
89 | //\r | |
90 | // Quark North Cluster devices\r | |
91 | //\r | |
92 | PCI_DEVICE (0, 0, 0),\r | |
93 | PCI_REG_MASK (0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
94 | \r | |
95 | PCI_DEVICE (0, 23, 0),\r | |
96 | PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
97 | \r | |
98 | PCI_DEVICE (0, 23, 1),\r | |
99 | PCI_REG_MASK (0xC0, 0x8F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00),\r | |
100 | \r | |
101 | PCI_DEVICE (0, 31, 0),\r | |
102 | PCI_REG_MASK (0x00, 0x08, 0x4E, 0x03, 0x02, 0x00, 0x60, 0x10),\r | |
103 | \r | |
104 | PCI_DEVICE_END\r | |
105 | };\r | |
106 | \r | |
107 | EFI_PLATFORM_TYPE mPlatformType;\r | |
108 | \r | |
109 | // These registers have to set in byte order\r | |
110 | const UINT8 QNCS3SaveExtReg[] = {\r | |
111 | QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, // SMRAM settings\r | |
112 | \r | |
113 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL,\r | |
114 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXH,\r | |
115 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r | |
116 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r | |
117 | \r | |
118 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXL,\r | |
119 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXH,\r | |
120 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r | |
121 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR1+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r | |
122 | \r | |
123 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXL,\r | |
124 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXH,\r | |
125 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r | |
126 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR2+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r | |
127 | \r | |
128 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXL,\r | |
129 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXH,\r | |
130 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r | |
131 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR3+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r | |
132 | \r | |
133 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXL,\r | |
134 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXH,\r | |
135 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r | |
136 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR4+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r | |
137 | \r | |
138 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXL,\r | |
139 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXH,\r | |
140 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r | |
141 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR5+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r | |
142 | \r | |
143 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXL,\r | |
144 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXH,\r | |
145 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r | |
146 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR6+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r | |
147 | \r | |
148 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXL,\r | |
149 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXH,\r | |
150 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXRM,\r | |
151 | QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM,\r | |
152 | \r | |
153 | QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_END_MEM_REG, // ECC Scrub settings\r | |
154 | QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_START_MEM_REG,\r | |
155 | QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_NEXT_READ_REG,\r | |
156 | QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG,\r | |
157 | \r | |
158 | 0xFF\r | |
159 | };\r | |
160 | \r | |
161 | /**\r | |
162 | Allocate EfiACPIMemoryNVS below 4G memory address.\r | |
163 | \r | |
164 | This function allocates EfiACPIMemoryNVS below 4G memory address.\r | |
165 | \r | |
166 | @param Size Size of memory to allocate.\r | |
167 | \r | |
168 | @return Allocated address for output.\r | |
169 | \r | |
170 | **/\r | |
171 | VOID*\r | |
172 | AllocateAcpiNvsMemoryBelow4G (\r | |
173 | IN UINTN Size\r | |
174 | )\r | |
175 | {\r | |
176 | UINTN Pages;\r | |
177 | EFI_PHYSICAL_ADDRESS Address;\r | |
178 | EFI_STATUS Status;\r | |
179 | VOID* Buffer;\r | |
180 | \r | |
181 | Pages = EFI_SIZE_TO_PAGES (Size);\r | |
182 | Address = 0xffffffff;\r | |
183 | \r | |
184 | Status = gBS->AllocatePages (\r | |
185 | AllocateMaxAddress,\r | |
186 | EfiACPIMemoryNVS,\r | |
187 | Pages,\r | |
188 | &Address\r | |
189 | );\r | |
190 | if (EFI_ERROR (Status)) {\r | |
191 | return NULL;\r | |
192 | }\r | |
193 | \r | |
194 | Buffer = (VOID *) (UINTN) Address;\r | |
195 | ZeroMem (Buffer, Size);\r | |
196 | \r | |
197 | return Buffer;\r | |
198 | }\r | |
199 | \r | |
200 | EFI_STATUS\r | |
201 | EFIAPI\r | |
202 | ReservedS3Memory (\r | |
203 | UINTN SystemMemoryLength\r | |
204 | \r | |
205 | )\r | |
206 | /*++\r | |
207 | \r | |
208 | Routine Description:\r | |
209 | \r | |
210 | Reserved S3 memory for InstallS3Memory\r | |
211 | \r | |
212 | Arguments:\r | |
213 | \r | |
214 | \r | |
215 | Returns:\r | |
216 | \r | |
217 | EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.\r | |
218 | EFI_SUCCESS - Function has completed successfully.\r | |
219 | \r | |
220 | --*/\r | |
221 | {\r | |
222 | \r | |
223 | VOID *GuidHob;\r | |
224 | EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;\r | |
225 | VOID *AcpiReservedBase;\r | |
226 | \r | |
227 | UINTN TsegIndex;\r | |
228 | UINTN TsegSize;\r | |
229 | UINTN TsegBase;\r | |
230 | RESERVED_ACPI_S3_RANGE *AcpiS3Range;\r | |
231 | //\r | |
232 | // Get Hob list for SMRAM desc\r | |
233 | //\r | |
234 | GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r | |
235 | ASSERT (GuidHob);\r | |
236 | DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);\r | |
237 | ASSERT (DescriptorBlock);\r | |
238 | \r | |
239 | //\r | |
240 | // Use the hob to get SMRAM capabilities\r | |
241 | //\r | |
242 | TsegIndex = DescriptorBlock->NumberOfSmmReservedRegions - 1;\r | |
243 | ASSERT (TsegIndex <= (MAX_SMRAM_RANGES - 1));\r | |
244 | TsegBase = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalStart;\r | |
245 | TsegSize = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalSize;\r | |
246 | \r | |
247 | DEBUG ((EFI_D_INFO, "SMM Base: %08X\n", TsegBase));\r | |
248 | DEBUG ((EFI_D_INFO, "SMM Size: %08X\n", TsegSize));\r | |
249 | \r | |
250 | //\r | |
251 | // Now find the location of the data structure that is used to store the address\r | |
252 | // of the S3 reserved memory.\r | |
253 | //\r | |
254 | AcpiS3Range = (RESERVED_ACPI_S3_RANGE*) (UINTN) (TsegBase + RESERVED_ACPI_S3_RANGE_OFFSET);\r | |
255 | \r | |
256 | //\r | |
257 | // Allocate reserved ACPI memory for S3 resume. Pointer to this region is\r | |
258 | // stored in SMRAM in the first page of TSEG.\r | |
259 | //\r | |
260 | AcpiReservedBase = AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize));\r | |
261 | if (AcpiReservedBase != NULL) {\r | |
262 | AcpiS3Range->AcpiReservedMemoryBase = (UINT32)(UINTN) AcpiReservedBase;\r | |
263 | AcpiS3Range->AcpiReservedMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);\r | |
264 | }\r | |
265 | AcpiS3Range->SystemMemoryLength = (UINT32)SystemMemoryLength;\r | |
266 | \r | |
267 | DEBUG ((EFI_D_INFO, "S3 Memory Base: %08X\n", AcpiS3Range->AcpiReservedMemoryBase));\r | |
268 | DEBUG ((EFI_D_INFO, "S3 Memory Size: %08X\n", AcpiS3Range->AcpiReservedMemorySize));\r | |
269 | DEBUG ((EFI_D_INFO, "S3 SysMemoryLength: %08X\n", AcpiS3Range->SystemMemoryLength));\r | |
270 | \r | |
271 | return EFI_SUCCESS;\r | |
272 | }\r | |
273 | \r | |
274 | \r | |
275 | EFI_STATUS\r | |
276 | EFIAPI\r | |
277 | InitAcpiSmmPlatform (\r | |
278 | IN EFI_HANDLE ImageHandle,\r | |
279 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
280 | )\r | |
281 | /*++\r | |
282 | \r | |
283 | Routine Description:\r | |
284 | \r | |
285 | Initializes the SMM S3 Handler Driver.\r | |
286 | \r | |
287 | Arguments:\r | |
288 | \r | |
289 | ImageHandle - The image handle of Sleep State Wake driver.\r | |
290 | SystemTable - The starndard EFI system table.\r | |
291 | \r | |
292 | Returns:\r | |
293 | \r | |
294 | EFI_OUT_OF_RESOURCES - Insufficient resources to complete function.\r | |
295 | EFI_SUCCESS - Function has completed successfully.\r | |
296 | Other - Error occured during execution.\r | |
297 | \r | |
298 | --*/\r | |
299 | {\r | |
300 | EFI_STATUS Status;\r | |
301 | EFI_GLOBAL_NVS_AREA_PROTOCOL *AcpiNvsProtocol = NULL;\r | |
302 | UINTN MemoryLength;\r | |
303 | EFI_PEI_HOB_POINTERS Hob;\r | |
304 | \r | |
305 | Status = gBS->LocateProtocol (\r | |
306 | &gEfiGlobalNvsAreaProtocolGuid,\r | |
307 | NULL,\r | |
308 | (VOID **) &AcpiNvsProtocol\r | |
309 | );\r | |
310 | ASSERT_EFI_ERROR (Status);\r | |
311 | \r | |
312 | mAcpiSmm.BootScriptSaved = 0;\r | |
313 | \r | |
314 | mPlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);\r | |
315 | \r | |
316 | //\r | |
317 | // Calculate the system memory length by memory hobs\r | |
318 | //\r | |
319 | MemoryLength = 0x100000;\r | |
320 | Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r | |
321 | ASSERT (Hob.Raw != NULL);\r | |
322 | while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {\r | |
323 | if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r | |
324 | //\r | |
325 | // Skip the memory region below 1MB\r | |
326 | //\r | |
327 | if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {\r | |
328 | MemoryLength += (UINTN)Hob.ResourceDescriptor->ResourceLength;\r | |
329 | }\r | |
330 | }\r | |
331 | Hob.Raw = GET_NEXT_HOB (Hob);\r | |
332 | Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);\r | |
333 | }\r | |
334 | \r | |
335 | ReservedS3Memory(MemoryLength);\r | |
336 | \r | |
337 | //\r | |
338 | // Locate and Register to Parent driver\r | |
339 | //\r | |
340 | Status = RegisterToDispatchDriver ();\r | |
341 | ASSERT_EFI_ERROR (Status);\r | |
342 | \r | |
343 | return EFI_SUCCESS;\r | |
344 | }\r | |
345 | \r | |
346 | EFI_STATUS\r | |
347 | RegisterToDispatchDriver (\r | |
348 | VOID\r | |
349 | )\r | |
350 | /*++\r | |
351 | \r | |
352 | Routine Description:\r | |
353 | \r | |
354 | Register to dispatch driver.\r | |
355 | \r | |
356 | Arguments:\r | |
357 | \r | |
358 | None.\r | |
359 | \r | |
360 | Returns:\r | |
361 | \r | |
362 | EFI_SUCCESS - Successfully init the device.\r | |
363 | Other - Error occured whening calling Dxe lib functions.\r | |
364 | \r | |
365 | --*/\r | |
366 | {\r | |
367 | UINTN Length;\r | |
368 | EFI_STATUS Status;\r | |
369 | EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;\r | |
370 | EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;\r | |
371 | EFI_SMM_SX_REGISTER_CONTEXT *EntryDispatchContext;\r | |
372 | EFI_SMM_SX_REGISTER_CONTEXT *EntryS1DispatchContext;\r | |
373 | EFI_SMM_SX_REGISTER_CONTEXT *EntryS3DispatchContext;\r | |
374 | EFI_SMM_SX_REGISTER_CONTEXT *EntryS4DispatchContext;\r | |
375 | EFI_SMM_SX_REGISTER_CONTEXT *EntryS5DispatchContext;\r | |
376 | EFI_SMM_SW_REGISTER_CONTEXT *SwContext;\r | |
377 | EFI_SMM_SW_REGISTER_CONTEXT *AcpiDisableSwContext;\r | |
378 | EFI_SMM_SW_REGISTER_CONTEXT *AcpiEnableSwContext;\r | |
379 | \r | |
380 | Status = gSmst->SmmLocateProtocol (\r | |
381 | &gEfiSmmSxDispatch2ProtocolGuid,\r | |
382 | NULL,\r | |
383 | (VOID **) &SxDispatch\r | |
384 | );\r | |
385 | if (EFI_ERROR (Status)) {\r | |
386 | return Status;\r | |
387 | }\r | |
388 | \r | |
389 | Status = gSmst->SmmLocateProtocol (\r | |
390 | &gEfiSmmSwDispatch2ProtocolGuid,\r | |
391 | NULL,\r | |
392 | (VOID **) &SwDispatch\r | |
393 | );\r | |
394 | if (EFI_ERROR (Status)) {\r | |
395 | return Status;\r | |
396 | }\r | |
397 | \r | |
398 | Length = sizeof (EFI_SMM_SX_REGISTER_CONTEXT) * 4 + sizeof (EFI_SMM_SW_REGISTER_CONTEXT) * 2;\r | |
399 | Status = gSmst->SmmAllocatePool (\r | |
400 | EfiRuntimeServicesData,\r | |
401 | Length,\r | |
402 | (VOID **) &EntryDispatchContext\r | |
403 | );\r | |
404 | if (EFI_ERROR (Status)) {\r | |
405 | return Status;\r | |
406 | }\r | |
407 | \r | |
408 | SetMem (EntryDispatchContext, Length, 0);\r | |
409 | \r | |
410 | EntryS1DispatchContext = EntryDispatchContext++;\r | |
411 | EntryS3DispatchContext = EntryDispatchContext++;\r | |
412 | EntryS4DispatchContext = EntryDispatchContext++;\r | |
413 | EntryS5DispatchContext = EntryDispatchContext++;\r | |
414 | \r | |
415 | SwContext = (EFI_SMM_SW_REGISTER_CONTEXT *)EntryDispatchContext;\r | |
416 | AcpiDisableSwContext = SwContext++;\r | |
417 | AcpiEnableSwContext = SwContext++;\r | |
418 | \r | |
419 | //\r | |
420 | // Register the enable handler\r | |
421 | //\r | |
422 | AcpiEnableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_ENABLE;\r | |
423 | Status = SwDispatch->Register (\r | |
424 | SwDispatch,\r | |
425 | EnableAcpiCallback,\r | |
426 | AcpiEnableSwContext,\r | |
427 | &(mAcpiSmm.DisableAcpiHandle)\r | |
428 | );\r | |
429 | \r | |
430 | //\r | |
431 | // Register the disable handler\r | |
432 | //\r | |
433 | AcpiDisableSwContext->SwSmiInputValue = EFI_ACPI_ACPI_DISABLE;\r | |
434 | Status = SwDispatch->Register (\r | |
435 | SwDispatch,\r | |
436 | DisableAcpiCallback,\r | |
437 | AcpiDisableSwContext,\r | |
438 | &(mAcpiSmm.EnableAcpiHandle)\r | |
439 | );\r | |
440 | \r | |
441 | \r | |
442 | //\r | |
443 | // Register entry phase call back function for S1\r | |
444 | //\r | |
445 | EntryS1DispatchContext->Type = SxS1;\r | |
446 | EntryS1DispatchContext->Phase = SxEntry;\r | |
447 | Status = SxDispatch->Register (\r | |
448 | SxDispatch,\r | |
449 | SxSleepEntryCallBack,\r | |
450 | EntryS1DispatchContext,\r | |
451 | &(mAcpiSmm.S1SleepEntryHandle)\r | |
452 | );\r | |
453 | \r | |
454 | //\r | |
455 | // Register entry phase call back function\r | |
456 | //\r | |
457 | EntryS3DispatchContext->Type = SxS3;\r | |
458 | EntryS3DispatchContext->Phase = SxEntry;\r | |
459 | Status = SxDispatch->Register (\r | |
460 | SxDispatch,\r | |
461 | SxSleepEntryCallBack,\r | |
462 | EntryS3DispatchContext,\r | |
463 | &(mAcpiSmm.S3SleepEntryHandle)\r | |
464 | );\r | |
465 | \r | |
466 | //\r | |
467 | // Register entry phase call back function for S4\r | |
468 | //\r | |
469 | EntryS4DispatchContext->Type = SxS4;\r | |
470 | EntryS4DispatchContext->Phase = SxEntry;\r | |
471 | Status = SxDispatch->Register (\r | |
472 | SxDispatch,\r | |
473 | SxSleepEntryCallBack,\r | |
474 | EntryS4DispatchContext,\r | |
475 | &(mAcpiSmm.S4SleepEntryHandle)\r | |
476 | );\r | |
477 | \r | |
478 | //\r | |
479 | // Register callback for S5 in order to workaround the LAN shutdown issue\r | |
480 | //\r | |
481 | EntryS5DispatchContext->Type = SxS5;\r | |
482 | EntryS5DispatchContext->Phase = SxEntry;\r | |
483 | Status = SxDispatch->Register (\r | |
484 | SxDispatch,\r | |
485 | SxSleepEntryCallBack,\r | |
486 | EntryS5DispatchContext,\r | |
487 | &(mAcpiSmm.S5SoftOffEntryHandle)\r | |
488 | );\r | |
489 | \r | |
490 | return Status;\r | |
491 | }\r | |
492 | \r | |
493 | \r | |
494 | EFI_STATUS\r | |
495 | RestoreQncS3SwCallback (\r | |
496 | IN EFI_HANDLE DispatchHandle,\r | |
497 | IN CONST VOID *DispatchContext,\r | |
498 | IN OUT VOID *CommBuffer,\r | |
499 | IN OUT UINTN *CommBufferSize\r | |
500 | )\r | |
501 | /*++\r | |
502 | \r | |
503 | Routine Description:\r | |
504 | SMI handler to retore QncS3 code & context for S3 path\r | |
505 | This will be only triggered when BootScript got executed during resume\r | |
506 | \r | |
507 | Arguments:\r | |
508 | DispatchHandle - EFI Handle\r | |
509 | DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT\r | |
510 | \r | |
511 | Returns:\r | |
512 | Nothing\r | |
513 | \r | |
514 | --*/\r | |
515 | {\r | |
516 | //\r | |
517 | // Restore to original address by default\r | |
518 | //\r | |
519 | RestoreLockBox(&gQncS3CodeInLockBoxGuid, NULL, NULL);\r | |
520 | RestoreLockBox(&gQncS3ContextInLockBoxGuid, NULL, NULL);\r | |
521 | return EFI_SUCCESS;\r | |
522 | }\r | |
523 | \r | |
524 | EFI_STATUS\r | |
525 | DisableAcpiCallback (\r | |
526 | IN EFI_HANDLE DispatchHandle,\r | |
527 | IN CONST VOID *DispatchContext,\r | |
528 | IN OUT VOID *CommBuffer,\r | |
529 | IN OUT UINTN *CommBufferSize\r | |
530 | )\r | |
531 | /*++\r | |
532 | \r | |
533 | Routine Description:\r | |
534 | SMI handler to disable ACPI mode\r | |
535 | \r | |
536 | Dispatched on reads from APM port with value 0xA1\r | |
537 | \r | |
538 | ACPI events are disabled and ACPI event status is cleared.\r | |
539 | SCI mode is then disabled.\r | |
540 | Clear all ACPI event status and disable all ACPI events\r | |
541 | Disable PM sources except power button\r | |
542 | Clear status bits\r | |
543 | Disable GPE0 sources\r | |
544 | Clear status bits\r | |
545 | Disable GPE1 sources\r | |
546 | Clear status bits\r | |
547 | Disable SCI\r | |
548 | \r | |
549 | Arguments:\r | |
550 | DispatchHandle - EFI Handle\r | |
551 | DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT\r | |
552 | \r | |
553 | Returns:\r | |
554 | Nothing\r | |
555 | \r | |
556 | --*/\r | |
557 | {\r | |
558 | EFI_STATUS Status;\r | |
559 | UINT16 Pm1Cnt;\r | |
560 | \r | |
561 | Status = GetAllQncPmBase (gSmst);\r | |
562 | ASSERT_EFI_ERROR (Status);\r | |
563 | Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);\r | |
564 | \r | |
565 | //\r | |
566 | // Disable SCI\r | |
567 | //\r | |
568 | Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SCIEN;\r | |
569 | \r | |
570 | IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);\r | |
571 | \r | |
572 | return EFI_SUCCESS;\r | |
573 | }\r | |
574 | \r | |
575 | EFI_STATUS\r | |
576 | EnableAcpiCallback (\r | |
577 | IN EFI_HANDLE DispatchHandle,\r | |
578 | IN CONST VOID *DispatchContext,\r | |
579 | IN OUT VOID *CommBuffer,\r | |
580 | IN OUT UINTN *CommBufferSize\r | |
581 | )\r | |
582 | /*++\r | |
583 | \r | |
584 | Routine Description:\r | |
585 | SMI handler to enable ACPI mode\r | |
586 | \r | |
587 | Dispatched on reads from APM port with value 0xA0\r | |
588 | \r | |
589 | Disables the SW SMI Timer.\r | |
590 | ACPI events are disabled and ACPI event status is cleared.\r | |
591 | SCI mode is then enabled.\r | |
592 | \r | |
593 | Disable SW SMI Timer\r | |
594 | \r | |
595 | Clear all ACPI event status and disable all ACPI events\r | |
596 | Disable PM sources except power button\r | |
597 | Clear status bits\r | |
598 | \r | |
599 | Disable GPE0 sources\r | |
600 | Clear status bits\r | |
601 | \r | |
602 | Disable GPE1 sources\r | |
603 | Clear status bits\r | |
604 | \r | |
605 | Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)\r | |
606 | \r | |
607 | Enable SCI\r | |
608 | \r | |
609 | Arguments:\r | |
610 | DispatchHandle - EFI Handle\r | |
611 | DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT\r | |
612 | \r | |
613 | Returns:\r | |
614 | Nothing\r | |
615 | \r | |
616 | --*/\r | |
617 | {\r | |
618 | EFI_STATUS Status;\r | |
619 | UINT32 SmiEn;\r | |
620 | UINT16 Pm1Cnt;\r | |
621 | UINT8 Data8;\r | |
622 | \r | |
623 | Status = GetAllQncPmBase (gSmst);\r | |
624 | ASSERT_EFI_ERROR (Status);\r | |
625 | \r | |
626 | SmiEn = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);\r | |
627 | \r | |
628 | //\r | |
629 | // Disable SW SMI Timer\r | |
630 | //\r | |
631 | SmiEn &= ~(B_QNC_GPE0BLK_SMIE_SWT);\r | |
632 | IoWrite32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE, SmiEn);\r | |
633 | \r | |
634 | //\r | |
635 | // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)\r | |
636 | //\r | |
637 | Data8 = RTC_ADDRESS_REGISTER_D;\r | |
638 | IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);\r | |
639 | Data8 = 0x0;\r | |
640 | IoWrite8 (R_IOPORT_CMOS_STANDARD_DATA, Data8);\r | |
641 | \r | |
642 | //\r | |
643 | // Enable SCI\r | |
644 | //\r | |
645 | Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);\r | |
646 | Pm1Cnt |= B_QNC_PM1BLK_PM1C_SCIEN;\r | |
647 | IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);\r | |
648 | \r | |
649 | //\r | |
650 | // Do platform specific stuff for ACPI enable SMI\r | |
651 | //\r | |
652 | \r | |
653 | \r | |
654 | return EFI_SUCCESS;\r | |
655 | }\r | |
656 | \r | |
657 | EFI_STATUS\r | |
658 | SxSleepEntryCallBack (\r | |
659 | IN EFI_HANDLE DispatchHandle,\r | |
660 | IN CONST VOID *DispatchContext,\r | |
661 | IN OUT VOID *CommBuffer,\r | |
662 | IN OUT UINTN *CommBufferSize\r | |
663 | )\r | |
664 | /*++\r | |
665 | \r | |
666 | Routine Description:\r | |
667 | \r | |
668 | Callback function entry for Sx sleep state.\r | |
669 | \r | |
670 | Arguments:\r | |
671 | \r | |
672 | DispatchHandle - The handle of this callback, obtained when registering.\r | |
673 | DispatchContext - The predefined context which contained sleep type and phase.\r | |
674 | \r | |
675 | Returns:\r | |
676 | \r | |
677 | EFI_SUCCESS - Operation successfully performed.\r | |
678 | EFI_INVALID_PARAMETER - Invalid parameter passed in.\r | |
679 | \r | |
680 | --*/\r | |
681 | {\r | |
682 | EFI_STATUS Status;\r | |
683 | UINT8 Data8;\r | |
684 | UINT16 Data16;\r | |
685 | UINT32 Data32;\r | |
686 | \r | |
687 | REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeS3SuspendStart));\r | |
688 | \r | |
689 | //\r | |
690 | // Reget QNC power mgmr regs base in case of OS changing it at runtime\r | |
691 | //\r | |
692 | Status = GetAllQncPmBase (gSmst);\r | |
693 | \r | |
694 | //\r | |
695 | // Clear RTC Alarm (if set)\r | |
696 | //\r | |
697 | Data8 = RTC_ADDRESS_REGISTER_C;\r | |
698 | IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);\r | |
699 | Data8 = IoRead8 (R_IOPORT_CMOS_STANDARD_DATA);\r | |
700 | \r | |
701 | //\r | |
702 | // Clear all ACPI status bits\r | |
703 | //\r | |
704 | Data32 = B_QNC_GPE0BLK_GPE0S_ALL;\r | |
705 | Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0S, 1, &Data32 );\r | |
706 | Data16 = B_QNC_PM1BLK_PM1S_ALL;\r | |
707 | Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1S, 1, &Data16 );\r | |
708 | \r | |
709 | //\r | |
710 | // Handling S1 - setting appropriate wake bits in GPE0_EN\r | |
711 | //\r | |
712 | if ((DispatchHandle == mAcpiSmm.S1SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS1)) {\r | |
713 | //\r | |
714 | // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN\r | |
715 | //\r | |
716 | Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r | |
717 | Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);\r | |
718 | Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r | |
719 | \r | |
720 | //\r | |
721 | // Enable bit10 (RTC) in PM1E\r | |
722 | //\r | |
723 | Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r | |
724 | Data16 |= B_QNC_PM1BLK_PM1E_RTC;\r | |
725 | Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r | |
726 | \r | |
727 | return EFI_SUCCESS;\r | |
728 | }\r | |
729 | \r | |
730 | //\r | |
731 | // Handling S4, S5 and WOL - setting appropriate wake bits in GPE0_EN\r | |
732 | //\r | |
733 | if (((DispatchHandle == mAcpiSmm.S4SleepEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS4)) ||\r | |
734 | ((DispatchHandle == mAcpiSmm.S5SoftOffEntryHandle) && (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type == SxS5))\r | |
735 | ) {\r | |
736 | //\r | |
737 | // Enable bit13 (EGPE), 14 (GPIO) ,17 (PCIE) in GPE0_EN\r | |
738 | // Enable the WOL bits in GPE0_EN reg here for PME\r | |
739 | //\r | |
740 | Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r | |
741 | Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);\r | |
742 | Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r | |
743 | \r | |
744 | //\r | |
745 | // Enable bit10 (RTC) in PM1E\r | |
746 | //\r | |
747 | Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r | |
748 | Data16 |= B_QNC_PM1BLK_PM1E_RTC;\r | |
749 | Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r | |
750 | \r | |
751 | } else {\r | |
752 | \r | |
753 | if ((DispatchHandle != mAcpiSmm.S3SleepEntryHandle) || (((EFI_SMM_SX_REGISTER_CONTEXT *)DispatchContext)->Type != SxS3)) {\r | |
754 | return EFI_INVALID_PARAMETER;\r | |
755 | }\r | |
756 | \r | |
757 | Status = SaveRuntimeScriptTable (gSmst);\r | |
758 | if (EFI_ERROR (Status)) {\r | |
759 | return Status;\r | |
760 | }\r | |
761 | \r | |
762 | //\r | |
763 | // Enable bit13 (EGPE), 14 (GPIO), 17 (PCIE) in GPE0_EN\r | |
764 | // Enable the WOL bits in GPE0_EN reg here for PME\r | |
765 | //\r | |
766 | Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r | |
767 | Data32 |= (B_QNC_GPE0BLK_GPE0E_EGPE | B_QNC_GPE0BLK_GPE0E_GPIO | B_QNC_GPE0BLK_GPE0E_PCIE);\r | |
768 | Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT32, mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_GPE0E, 1, &Data32 );\r | |
769 | \r | |
770 | //\r | |
771 | // Enable bit10 (RTC) in PM1E\r | |
772 | //\r | |
773 | Status = gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r | |
774 | Data16 |= B_QNC_PM1BLK_PM1E_RTC;\r | |
775 | Status = gSmst->SmmIo.Io.Write( &gSmst->SmmIo, SMM_IO_UINT16, mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1E, 1, &Data16 );\r | |
776 | }\r | |
777 | \r | |
778 | //\r | |
779 | // When entering a power-managed state like S3,\r | |
780 | // PERST# must be asserted in advance of power-off.\r | |
781 | //\r | |
782 | PlatformPERSTAssert (mPlatformType);\r | |
783 | \r | |
784 | return EFI_SUCCESS;\r | |
785 | }\r | |
786 | \r | |
787 | EFI_STATUS\r | |
788 | GetAllQncPmBase (\r | |
789 | IN EFI_SMM_SYSTEM_TABLE2 *Smst\r | |
790 | )\r | |
791 | /*++\r | |
792 | \r | |
793 | Routine Description:\r | |
794 | \r | |
795 | Get QNC chipset LPC Power Management I/O Base at runtime.\r | |
796 | \r | |
797 | Arguments:\r | |
798 | \r | |
799 | Smst - The standard SMM system table.\r | |
800 | \r | |
801 | Returns:\r | |
802 | \r | |
803 | EFI_SUCCESS - Successfully init the device.\r | |
804 | Other - Error occured whening calling Dxe lib functions.\r | |
805 | \r | |
806 | --*/\r | |
807 | {\r | |
808 | mAcpiSmm.QncPmBase = PciRead16 (PCI_LIB_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, R_QNC_LPC_PM1BLK)) & B_QNC_LPC_PM1BLK_MASK;\r | |
809 | mAcpiSmm.QncGpe0Base = PciRead16 (PCI_LIB_ADDRESS(PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, 0, R_QNC_LPC_GPE0BLK)) & B_QNC_LPC_GPE0BLK_MASK;\r | |
810 | \r | |
811 | //\r | |
812 | // Quark does not support Changing Primary SoC IOBARs from what was\r | |
813 | // setup in SEC/PEI UEFI stages.\r | |
814 | //\r | |
815 | ASSERT (mAcpiSmm.QncPmBase == (UINT32) PcdGet16 (PcdPm1blkIoBaseAddress));\r | |
816 | ASSERT (mAcpiSmm.QncGpe0Base == (UINT32) PcdGet16 (PcdGpe0blkIoBaseAddress));\r | |
817 | return EFI_SUCCESS;\r | |
818 | }\r | |
819 | \r | |
820 | EFI_STATUS\r | |
821 | SaveRuntimeScriptTable (\r | |
822 | IN EFI_SMM_SYSTEM_TABLE2 *Smst\r | |
823 | )\r | |
824 | {\r | |
825 | EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r | |
826 | UINT32 Data32;\r | |
827 | UINT16 Data16;\r | |
828 | UINT8 Mask;\r | |
829 | UINTN Index;\r | |
830 | UINTN Offset;\r | |
831 | UINT16 DeviceId;\r | |
832 | \r | |
833 | //\r | |
834 | // Check what Soc we are running on (read Host bridge DeviceId)\r | |
835 | //\r | |
836 | DeviceId = QncGetSocDeviceId();\r | |
837 | \r | |
838 | //\r | |
839 | // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM\r | |
840 | // and vital to S3 resume. That's why we put save code here\r | |
841 | //\r | |
842 | Index = 0;\r | |
843 | while (mPciCfgRegTable[Index] != PCI_DEVICE_END) {\r | |
844 | \r | |
845 | PciAddress.Bus = mPciCfgRegTable[Index++];\r | |
846 | PciAddress.Device = mPciCfgRegTable[Index++];\r | |
847 | PciAddress.Function = mPciCfgRegTable[Index++];\r | |
848 | PciAddress.Register = 0;\r | |
849 | PciAddress.ExtendedRegister = 0;\r | |
850 | \r | |
851 | Data16 = PciRead16 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));\r | |
852 | if (Data16 == 0xFFFF) {\r | |
853 | Index += 8;\r | |
854 | continue;\r | |
855 | }\r | |
856 | \r | |
857 | for (Offset = 0, Mask = 0x01; Offset < 256; Offset += 4, Mask <<= 1) {\r | |
858 | \r | |
859 | if (Mask == 0x00) {\r | |
860 | Mask = 0x01;\r | |
861 | }\r | |
862 | \r | |
863 | if (mPciCfgRegTable[Index + Offset / 32] & Mask) {\r | |
864 | \r | |
865 | PciAddress.Register = (UINT8) Offset;\r | |
866 | Data32 = PciRead32 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));\r | |
867 | \r | |
868 | \r | |
869 | //\r | |
870 | // Save latest settings to runtime script table\r | |
871 | //\r | |
872 | S3BootScriptSavePciCfgWrite (\r | |
873 | S3BootScriptWidthUint32,\r | |
874 | PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)),\r | |
875 | 1,\r | |
876 | &Data32\r | |
877 | );\r | |
878 | }\r | |
879 | }\r | |
880 | \r | |
881 | Index += 8;\r | |
882 | \r | |
883 | }\r | |
884 | \r | |
885 | //\r | |
886 | // Save message bus registers\r | |
887 | //\r | |
888 | Index = 0;\r | |
889 | while (QNCS3SaveExtReg[Index] != 0xFF) {\r | |
890 | Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r | |
891 | \r | |
892 | //\r | |
893 | // Save IMR settings with IMR protection disabled initially\r | |
894 | // HMBOUND and IMRs will be locked just before jumping to the OS waking vector\r | |
895 | //\r | |
896 | if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {\r | |
897 | if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {\r | |
898 | Data32 &= ~IMR_LOCK;\r | |
899 | if (DeviceId == QUARK2_MC_DEVICE_ID) {\r | |
900 | Data32 &= ~IMR_EN;\r | |
901 | }\r | |
902 | }\r | |
903 | if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {\r | |
904 | Data32 = (UINT32)IMRX_ALL_ACCESS;\r | |
905 | }\r | |
906 | }\r | |
907 | \r | |
908 | //\r | |
909 | // Save latest settings to runtime script table\r | |
910 | //\r | |
911 | S3BootScriptSavePciCfgWrite (\r | |
912 | S3BootScriptWidthUint32,\r | |
913 | PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),\r | |
914 | 1,\r | |
915 | &Data32\r | |
916 | );\r | |
917 | \r | |
918 | Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r | |
919 | \r | |
920 | S3BootScriptSavePciCfgWrite (\r | |
921 | S3BootScriptWidthUint32,\r | |
922 | PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r | |
923 | 1,\r | |
924 | &Data32\r | |
925 | );\r | |
926 | Index += 2;\r | |
927 | }\r | |
928 | \r | |
929 | Index = 0;\r | |
930 | while (QNCS3SaveExtReg[Index] != 0xFF) {\r | |
931 | //\r | |
932 | // Save IMR settings with IMR protection enabled (above script was to handle restoring all settings first - now we want to enable)\r | |
933 | //\r | |
934 | if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {\r | |
935 | if (DeviceId == QUARK2_MC_DEVICE_ID) {\r | |
936 | if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {\r | |
937 | Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r | |
938 | Data32 &= ~IMR_LOCK;\r | |
939 | \r | |
940 | //\r | |
941 | // Save latest settings to runtime script table\r | |
942 | //\r | |
943 | S3BootScriptSavePciCfgWrite (\r | |
944 | S3BootScriptWidthUint32,\r | |
945 | PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),\r | |
946 | 1,\r | |
947 | &Data32\r | |
948 | );\r | |
949 | \r | |
950 | Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r | |
951 | \r | |
952 | S3BootScriptSavePciCfgWrite (\r | |
953 | S3BootScriptWidthUint32,\r | |
954 | PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r | |
955 | 1,\r | |
956 | &Data32\r | |
957 | );\r | |
958 | }\r | |
959 | } else {\r | |
960 | if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {\r | |
961 | Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r | |
962 | \r | |
963 | //\r | |
964 | // Save latest settings to runtime script table\r | |
965 | //\r | |
966 | S3BootScriptSavePciCfgWrite (\r | |
967 | S3BootScriptWidthUint32,\r | |
968 | PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),\r | |
969 | 1,\r | |
970 | &Data32\r | |
971 | );\r | |
972 | \r | |
973 | Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);\r | |
974 | \r | |
975 | S3BootScriptSavePciCfgWrite (\r | |
976 | S3BootScriptWidthUint32,\r | |
977 | PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r | |
978 | 1,\r | |
979 | &Data32\r | |
980 | );\r | |
981 | }\r | |
982 | }\r | |
983 | }\r | |
984 | Index += 2;\r | |
985 | }\r | |
986 | \r | |
987 | // Check if ECC scrub enabled and need re-enabling on resume\r | |
988 | // All scrub related configuration registers are saved on suspend\r | |
989 | // as part of QNCS3SaveExtReg configuration table script.\r | |
990 | // The code below extends the S3 resume script with scrub reactivation\r | |
991 | // message (if needed only)\r | |
992 | Data32 = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG);\r | |
993 | if( 0 != (Data32 & SCRUB_CFG_ACTIVE)) {\r | |
994 | \r | |
995 | Data32 = SCRUB_RESUME_MSG();\r | |
996 | \r | |
997 | S3BootScriptSavePciCfgWrite (\r | |
998 | S3BootScriptWidthUint32,\r | |
999 | PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),\r | |
1000 | 1,\r | |
1001 | &Data32\r | |
1002 | );\r | |
1003 | }\r | |
1004 | \r | |
1005 | //\r | |
1006 | // Save I/O ports to S3 script table\r | |
1007 | //\r | |
1008 | \r | |
1009 | //\r | |
1010 | // Important to trap Sx for SMM\r | |
1011 | //\r | |
1012 | Data32 = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);\r | |
1013 | S3BootScriptSaveIoWrite(S3BootScriptWidthUint32, (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE), 1, &Data32);\r | |
1014 | \r | |
1015 | return EFI_SUCCESS;\r | |
1016 | }\r | |
1017 | \r |