]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkSocPkg/QuarkNorthCluster/QNCInit/Dxe/QNCInit.c
QuarkSocPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / QNCInit / Dxe / QNCInit.c
CommitLineData
9b6bbcdb
MK
1/** @file\r
2QuarkNcSocId module initialization module\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#include "CommonHeader.h"\r
10\r
11#include "LegacyRegion.h"\r
12#include "DxeQNCSmbus.h"\r
13\r
14#include "QNCInit.h"\r
15\r
16//\r
17// Definitions\r
18//\r
19#define QNC_RESERVED_ITEM_IO 0\r
20#define QNC_RESERVED_ITEM_MEMORYIO 1\r
21#define DXE_DEVICE_DISABLED 0\r
22#define DXE_DEVICE_ENABLED 1\r
23\r
24typedef struct _QNC_SPACE_TABLE_ITEM {\r
25 UINTN IoOrMemory;\r
26 UINTN Type;\r
27 EFI_PHYSICAL_ADDRESS BaseAddress;\r
28 UINT64 Length;\r
29 UINTN Alignment;\r
30 BOOLEAN RuntimeOrNot;\r
31} QNC_SPACE_TABLE_ITEM;\r
32\r
33typedef struct {\r
34 ACPI_CPU_DATA AcpuCpuData;\r
35 MTRR_SETTINGS MtrrTable;\r
36 IA32_DESCRIPTOR GdtrProfile;\r
37 IA32_DESCRIPTOR IdtrProfile;\r
38 CPU_REGISTER_TABLE RegisterTable;\r
39 CPU_REGISTER_TABLE PreSmmInitRegisterTable;\r
40} ACPI_CPU_DATA_EX;\r
41\r
42//\r
43// Spaces to be reserved in GCD\r
44// Expand it to add more\r
45//\r
46const QNC_SPACE_TABLE_ITEM mQNCReservedSpaceTable[] = {\r
47 {\r
48 QNC_RESERVED_ITEM_MEMORYIO,\r
49 EfiGcdMemoryTypeMemoryMappedIo,\r
50 FixedPcdGet64 (PcdIoApicBaseAddress),\r
51 FixedPcdGet64 (PcdIoApicSize),\r
52 0,\r
53 FALSE\r
54 },\r
55 {\r
56 QNC_RESERVED_ITEM_MEMORYIO,\r
57 EfiGcdMemoryTypeMemoryMappedIo,\r
58 FixedPcdGet64 (PcdHpetBaseAddress),\r
59 FixedPcdGet64 (PcdHpetSize),\r
60 0,\r
61 FALSE\r
62 }\r
63};\r
64\r
65//\r
66// Global variable for ImageHandle of QNCInit driver\r
67//\r
68EFI_HANDLE gQNCInitImageHandle;\r
69QNC_DEVICE_ENABLES mQNCDeviceEnables;\r
70\r
71\r
72VOID\r
73QNCInitializeResource (\r
74 VOID\r
75 );\r
76\r
77EFI_STATUS\r
78InitializeQNCPolicy (\r
79 VOID\r
80 );\r
81\r
82/**\r
83 Allocate EfiACPIMemoryNVS below 4G memory address.\r
84\r
85 This function allocates EfiACPIMemoryNVS below 4G memory address.\r
86\r
87 @param Size Size of memory to allocate.\r
88\r
89 @return Allocated address for output.\r
90\r
91**/\r
92VOID *\r
93AllocateAcpiNvsMemoryBelow4G (\r
94 IN UINTN Size\r
95 )\r
96{\r
97 UINTN Pages;\r
98 EFI_PHYSICAL_ADDRESS Address;\r
99 EFI_STATUS Status;\r
100 VOID* Buffer;\r
101\r
102 Pages = EFI_SIZE_TO_PAGES (Size);\r
103 Address = 0xffffffff;\r
104\r
105 Status = gBS->AllocatePages (\r
106 AllocateMaxAddress,\r
107 EfiACPIMemoryNVS,\r
108 Pages,\r
109 &Address\r
110 );\r
111 if (EFI_ERROR (Status)) {\r
112 return NULL;\r
113 }\r
114\r
115 Buffer = (VOID *) (UINTN) Address;\r
116 ZeroMem (Buffer, Size);\r
117\r
118 return Buffer;\r
119}\r
120\r
121/**\r
122 Prepare ACPI NVS memory below 4G memory for use of S3 resume.\r
123\r
124 This function allocates ACPI NVS memory below 4G memory for use of S3 resume,\r
125 and saves data into the memory region.\r
126\r
127**/\r
128VOID\r
129SaveCpuS3Data (\r
130 VOID\r
131 )\r
132{\r
133 EFI_STATUS Status;\r
134 ACPI_CPU_DATA_EX *AcpiCpuDataEx;\r
135 ACPI_CPU_DATA *AcpiCpuData;\r
136 UINTN GdtSize;\r
137 UINTN IdtSize;\r
138 VOID *Gdt;\r
139 VOID *Idt;\r
140\r
141 //\r
142 // Allocate ACPI NVS memory below 4G memory for use of S3 resume.\r
143 //\r
144 AcpiCpuDataEx = AllocateAcpiNvsMemoryBelow4G (sizeof (ACPI_CPU_DATA_EX));\r
145 AcpiCpuData = &AcpiCpuDataEx->AcpuCpuData;\r
146\r
147 //\r
148 //\r
149 //\r
150 AcpiCpuData->NumberOfCpus = 1;\r
151 AcpiCpuData->StackSize = PcdGet32 (PcdCpuApStackSize);\r
152 AcpiCpuData->ApMachineCheckHandlerBase = 0;\r
153 AcpiCpuData->ApMachineCheckHandlerSize = 0;\r
154 AcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->GdtrProfile;\r
155 AcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->IdtrProfile;\r
156 AcpiCpuData->MtrrTable = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->MtrrTable;\r
157 AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->RegisterTable;\r
158 AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS) (UINTN) &AcpiCpuDataEx->PreSmmInitRegisterTable;\r
159\r
160 //\r
161 // Allocate stack space for all CPUs\r
162 //\r
163 AcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateAcpiNvsMemoryBelow4G (AcpiCpuData->NumberOfCpus * AcpiCpuData->StackSize);\r
164\r
165 //\r
166 // Get MTRR settings from currently executing CPU\r
167 //\r
168 MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);\r
169\r
170 //\r
171 // Get the BSP's data of GDT and IDT\r
172 //\r
173 AsmReadGdtr ((IA32_DESCRIPTOR *) &AcpiCpuDataEx->GdtrProfile);\r
174 AsmReadIdtr ((IA32_DESCRIPTOR *) &AcpiCpuDataEx->IdtrProfile);\r
175\r
176 //\r
177 // Allocate GDT and IDT in ACPI NVS and copy in current GDT and IDT contents\r
178 //\r
179 GdtSize = AcpiCpuDataEx->GdtrProfile.Limit + 1;\r
180 IdtSize = AcpiCpuDataEx->IdtrProfile.Limit + 1;\r
181 Gdt = AllocateAcpiNvsMemoryBelow4G (GdtSize + IdtSize);\r
182 Idt = (VOID *)((UINTN)Gdt + GdtSize);\r
183 CopyMem (Gdt, (VOID *)AcpiCpuDataEx->GdtrProfile.Base, GdtSize);\r
184 CopyMem (Idt, (VOID *)AcpiCpuDataEx->IdtrProfile.Base, IdtSize);\r
185 AcpiCpuDataEx->GdtrProfile.Base = (UINTN)Gdt;\r
186 AcpiCpuDataEx->IdtrProfile.Base = (UINTN)Idt;\r
187\r
188 //\r
189 // No RegisterTable entries\r
190 //\r
191 AcpiCpuDataEx->RegisterTable.TableLength = 0;\r
192\r
193 //\r
194 // No PreSmmInitRegisterTable entries\r
195 //\r
196 AcpiCpuDataEx->PreSmmInitRegisterTable.TableLength = 0;\r
197\r
198 //\r
199 // Set the base address of CPU S3 data to PcdCpuS3DataAddress\r
200 //\r
201 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
202 ASSERT_EFI_ERROR (Status);\r
203}\r
204\r
205/**\r
206 The entry function for QNCInit driver.\r
207\r
208 This function just call initialization function for PciHostBridge,\r
209 LegacyRegion and QNCSmmAccess module.\r
210\r
211 @param ImageHandle The driver image handle for GmchInit driver\r
212 @param SystemTable The pointer to System Table\r
213\r
214 @retval EFI_SUCCESS Success to initialize every module for GMCH driver.\r
215 @return EFI_STATUS The status of initialization work.\r
216\r
217**/\r
218EFI_STATUS\r
219EFIAPI\r
220QNCInit (\r
221 IN EFI_HANDLE ImageHandle,\r
222 IN EFI_SYSTEM_TABLE *SystemTable\r
223 )\r
224{\r
225 EFI_STATUS Status;\r
226\r
227 S3BootScriptSaveInformationAsciiString (\r
228 "QNCInitDxeEntryBegin"\r
229 );\r
230\r
231 gQNCInitImageHandle = ImageHandle;\r
232\r
233 mQNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);\r
234\r
235\r
236 //\r
237 // Initialize PCIE root ports\r
238 //\r
239 Status = QncInitRootPorts ();\r
240 if (EFI_ERROR (Status)) {\r
241 DEBUG ((EFI_D_ERROR, "QNC Root Port initialization is failed!\n"));\r
242 return Status;\r
243 }\r
244\r
245 Status = LegacyRegionInit ();\r
246 if (EFI_ERROR (Status)) {\r
247 DEBUG ((EFI_D_ERROR, "QNC LegacyRegion initialization is failed!\n"));\r
248 return Status;\r
249 }\r
250\r
251\r
252 Status = InitializeQNCPolicy ();\r
253 if (EFI_ERROR (Status)) {\r
254 DEBUG ((EFI_D_ERROR, "QNC Policy initialization is failed!\n"));\r
255 return Status;\r
256 }\r
257\r
258 Status = InitializeQNCSmbus (ImageHandle,SystemTable);\r
259 if (EFI_ERROR (Status)) {\r
260 DEBUG ((EFI_D_ERROR, "QNC Smbus driver is failed!\n"));\r
261 return Status;\r
262 }\r
263\r
264 QNCInitializeResource ();\r
265\r
266 SaveCpuS3Data ();\r
267\r
268 S3BootScriptSaveInformationAsciiString (\r
269 "QNCInitDxeEntryEnd"\r
270 );\r
271\r
272 return EFI_SUCCESS;\r
273}\r
274\r
275\r
276/**\r
277 Reserve I/O or memory space in GCD\r
278\r
279 @param IoOrMemory Switch of I/O or memory.\r
280 @param GcdType Type of the space.\r
281 @param BaseAddress Base address of the space.\r
282 @param Length Length of the space.\r
283 @param Alignment Align with 2^Alignment\r
284 @param RuntimeOrNot For runtime usage or not\r
285 @param ImageHandle Handle for the image of this driver.\r
286\r
287 @retval EFI_SUCCESS Reserve successful\r
288**/\r
289EFI_STATUS\r
290QNCReserveSpaceInGcd(\r
291 IN UINTN IoOrMemory,\r
292 IN UINTN GcdType,\r
293 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
294 IN UINT64 Length,\r
295 IN UINTN Alignment,\r
296 IN BOOLEAN RuntimeOrNot,\r
297 IN EFI_HANDLE ImageHandle\r
298 )\r
299{\r
300 EFI_STATUS Status;\r
301\r
302 if (IoOrMemory == QNC_RESERVED_ITEM_MEMORYIO) {\r
303 Status = gDS->AddMemorySpace (\r
304 GcdType,\r
305 BaseAddress,\r
306 Length,\r
307 EFI_MEMORY_UC\r
308 );\r
309 if (EFI_ERROR (Status)) {\r
310 DEBUG ((\r
311 EFI_D_ERROR,\r
312 "Failed to add memory space :0x%x 0x%x\n",\r
313 BaseAddress,\r
314 Length\r
315 ));\r
316 }\r
317 ASSERT_EFI_ERROR (Status);\r
318 Status = gDS->AllocateMemorySpace (\r
319 EfiGcdAllocateAddress,\r
320 GcdType,\r
321 Alignment,\r
322 Length,\r
323 &BaseAddress,\r
324 ImageHandle,\r
325 NULL\r
326 );\r
327 ASSERT_EFI_ERROR (Status);\r
328 if (RuntimeOrNot) {\r
329 Status = gDS->SetMemorySpaceAttributes (\r
330 BaseAddress,\r
331 Length,\r
332 EFI_MEMORY_RUNTIME | EFI_MEMORY_UC\r
333 );\r
334 ASSERT_EFI_ERROR (Status);\r
335 }\r
336 } else {\r
337 Status = gDS->AddIoSpace (\r
338 GcdType,\r
339 BaseAddress,\r
340 Length\r
341 );\r
342 ASSERT_EFI_ERROR (Status);\r
343 Status = gDS->AllocateIoSpace (\r
344 EfiGcdAllocateAddress,\r
345 GcdType,\r
346 Alignment,\r
347 Length,\r
348 &BaseAddress,\r
349 ImageHandle,\r
350 NULL\r
351 );\r
352 ASSERT_EFI_ERROR (Status);\r
353 }\r
354 return Status;\r
355}\r
356\r
357\r
358/**\r
359 Initialize the memory and io resource which belong to QNC.\r
360 1) Report and allocate all BAR's memory to GCD.\r
361 2) Report PCI memory and I/O space to GCD.\r
362 3) Set memory attribute for <1M memory space.\r
363**/\r
364VOID\r
365QNCInitializeResource (\r
366 )\r
367{\r
368 EFI_PHYSICAL_ADDRESS BaseAddress;\r
369 EFI_STATUS Status;\r
370 UINT64 ExtraRegionLength;\r
371 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
372 UINTN Index;\r
373\r
374 // Report TSEG range\r
375 // This range maybe has been reportted in PEI phase via Resource Hob.\r
376 //\r
377 QNCGetTSEGMemoryRange (&BaseAddress, &ExtraRegionLength);\r
378 if (ExtraRegionLength != 0) {\r
379 Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &Descriptor);\r
380 if (Status == EFI_NOT_FOUND) {\r
381 Status = gDS->AddMemorySpace (\r
382 EfiGcdMemoryTypeReserved,\r
383 BaseAddress,\r
384 ExtraRegionLength,\r
385 EFI_MEMORY_UC\r
386 );\r
387 }\r
388 }\r
389\r
390 //\r
391 // < 1M resource setting. The memory ranges <1M has been added into GCD via\r
392 // resource hob produced by PEI phase. Here will set memory attribute of these\r
393 // ranges for DXE phase.\r
394 //\r
395\r
396 //\r
397 // Dos Area (0 ~ 0x9FFFFh)\r
398 //\r
399 Status = gDS->GetMemorySpaceDescriptor (0, &Descriptor);\r
400 DEBUG ((\r
401 EFI_D_INFO,\r
402 "DOS Area Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",\r
403 Descriptor.BaseAddress,\r
404 Descriptor.Length,\r
405 Descriptor.Attributes\r
406 ));\r
407 ASSERT_EFI_ERROR (Status);\r
408 Status = gDS->SetMemorySpaceAttributes(\r
409 0,\r
410 0xA0000,\r
411 EFI_MEMORY_WB\r
412 );\r
413 ASSERT_EFI_ERROR (Status);\r
414\r
415 //\r
416 // Default SMRAM UnCachable until SMBASE relocated.\r
417 //\r
418 Status = gDS->SetMemorySpaceAttributes(\r
419 0x30000,\r
420 0x10000,\r
421 EFI_MEMORY_UC\r
422 );\r
423 ASSERT_EFI_ERROR (Status);\r
424\r
425 //\r
426 // Default SMM ABSEG area. (0xA0000 ~ 0xBFFFF)\r
427 //\r
428 Status = gDS->GetMemorySpaceDescriptor (0xA0000, &Descriptor);\r
429 DEBUG ((\r
430 EFI_D_INFO,\r
431 "ABSEG Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",\r
432 Descriptor.BaseAddress,\r
433 Descriptor.Length,\r
434 Descriptor.Attributes\r
435 ));\r
436 ASSERT_EFI_ERROR (Status);\r
437 Status = gDS->SetMemorySpaceAttributes(\r
438 0xA0000,\r
439 0x20000,\r
440 EFI_MEMORY_UC\r
441 );\r
442 ASSERT_EFI_ERROR (Status);\r
443\r
444 //\r
445 // Expansion BIOS area.\r
446 //\r
447 Status = gDS->GetMemorySpaceDescriptor (0xC0000, &Descriptor);\r
448 DEBUG ((\r
449 EFI_D_INFO,\r
450 "Memory base = 0x%x, length = 0x%x, attribute = 0x%x\n",\r
451 Descriptor.BaseAddress,\r
452 Descriptor.Length,\r
453 Descriptor.Attributes\r
454 ));\r
455 ASSERT_EFI_ERROR (Status);\r
456 Status = gDS->SetMemorySpaceAttributes(\r
457 0xC0000,\r
458 0x30000,\r
459 EFI_MEMORY_UC\r
460 );\r
461 ASSERT_EFI_ERROR (Status);\r
462\r
463 //\r
464 // Report other IO resources from mQNCReservedSpaceTable in GCD\r
465 //\r
466 for (Index = 0; Index < sizeof (mQNCReservedSpaceTable) / sizeof (QNC_SPACE_TABLE_ITEM); Index++) {\r
467 Status = QNCReserveSpaceInGcd (\r
468 mQNCReservedSpaceTable[Index].IoOrMemory,\r
469 mQNCReservedSpaceTable[Index].Type,\r
470 mQNCReservedSpaceTable[Index].BaseAddress,\r
471 mQNCReservedSpaceTable[Index].Length,\r
472 mQNCReservedSpaceTable[Index].Alignment,\r
473 mQNCReservedSpaceTable[Index].RuntimeOrNot,\r
474 gQNCInitImageHandle\r
475 );\r
476 ASSERT_EFI_ERROR (Status);\r
477 }\r
478\r
479 //\r
480 // Report unused PCIe config space as reserved.\r
481 //\r
482 if (PcdGet64 (PcdPciExpressSize) < SIZE_256MB) {\r
483 Status = QNCReserveSpaceInGcd (\r
484 QNC_RESERVED_ITEM_MEMORYIO,\r
485 EfiGcdMemoryTypeMemoryMappedIo,\r
486 (PcdGet64(PcdPciExpressBaseAddress) + PcdGet64(PcdPciExpressSize)),\r
487 (SIZE_256MB - PcdGet64(PcdPciExpressSize)),\r
488 0,\r
489 FALSE,\r
490 gQNCInitImageHandle\r
491 );\r
492 ASSERT_EFI_ERROR (Status);\r
493 }\r
494}\r
495\r
496/**\r
497 Use the platform PCD to initialize devices in the QNC\r
498\r
499 @param ImageHandle Handle for the image of this driver.\r
500 @retval EFI_SUCCESS Initialize successful\r
501**/\r
502EFI_STATUS\r
503InitializeQNCPolicy (\r
504 )\r
505{\r
9b6bbcdb
MK
506 UINT32 PciD31F0RegBase; // LPC\r
507\r
9b6bbcdb
MK
508 PciD31F0RegBase = PciDeviceMmBase (PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC);\r
509\r
510 //\r
511 // Disable for smbus\r
512 //\r
513 if (mQNCDeviceEnables.Bits.Smbus == DXE_DEVICE_DISABLED) {\r
514 S3MmioAnd32 (PciD31F0RegBase + R_QNC_LPC_SMBUS_BASE, (~B_QNC_LPC_SMBUS_BASE_EN));\r
515 }\r
516\r
517 return EFI_SUCCESS;\r
518}\r