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