2 QuarkNcSocId module initialization module
4 Copyright (c) 2013-2015 Intel Corporation.
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "CommonHeader.h"
17 #include "LegacyRegion.h"
18 #include "DxeQNCSmbus.h"
25 #define QNC_RESERVED_ITEM_IO 0
26 #define QNC_RESERVED_ITEM_MEMORYIO 1
27 #define DXE_DEVICE_DISABLED 0
28 #define DXE_DEVICE_ENABLED 1
30 typedef struct _QNC_SPACE_TABLE_ITEM
{
33 EFI_PHYSICAL_ADDRESS BaseAddress
;
37 } QNC_SPACE_TABLE_ITEM
;
40 ACPI_CPU_DATA AcpuCpuData
;
41 MTRR_SETTINGS MtrrTable
;
42 IA32_DESCRIPTOR GdtrProfile
;
43 IA32_DESCRIPTOR IdtrProfile
;
44 CPU_REGISTER_TABLE RegisterTable
;
45 CPU_REGISTER_TABLE PreSmmInitRegisterTable
;
49 // Spaces to be reserved in GCD
50 // Expand it to add more
52 const QNC_SPACE_TABLE_ITEM mQNCReservedSpaceTable
[] = {
54 QNC_RESERVED_ITEM_MEMORYIO
,
55 EfiGcdMemoryTypeMemoryMappedIo
,
56 FixedPcdGet64 (PcdIoApicBaseAddress
),
57 FixedPcdGet64 (PcdIoApicSize
),
62 QNC_RESERVED_ITEM_MEMORYIO
,
63 EfiGcdMemoryTypeMemoryMappedIo
,
64 FixedPcdGet64 (PcdHpetBaseAddress
),
65 FixedPcdGet64 (PcdHpetSize
),
72 // Global variable for ImageHandle of QNCInit driver
74 EFI_HANDLE gQNCInitImageHandle
;
75 QNC_DEVICE_ENABLES mQNCDeviceEnables
;
79 QNCInitializeResource (
89 Allocate EfiACPIMemoryNVS below 4G memory address.
91 This function allocates EfiACPIMemoryNVS below 4G memory address.
93 @param Size Size of memory to allocate.
95 @return Allocated address for output.
99 AllocateAcpiNvsMemoryBelow4G (
104 EFI_PHYSICAL_ADDRESS Address
;
108 Pages
= EFI_SIZE_TO_PAGES (Size
);
109 Address
= 0xffffffff;
111 Status
= gBS
->AllocatePages (
117 if (EFI_ERROR (Status
)) {
121 Buffer
= (VOID
*) (UINTN
) Address
;
122 ZeroMem (Buffer
, Size
);
128 Prepare ACPI NVS memory below 4G memory for use of S3 resume.
130 This function allocates ACPI NVS memory below 4G memory for use of S3 resume,
131 and saves data into the memory region.
140 ACPI_CPU_DATA_EX
*AcpiCpuDataEx
;
141 ACPI_CPU_DATA
*AcpiCpuData
;
148 // Allocate ACPI NVS memory below 4G memory for use of S3 resume.
150 AcpiCpuDataEx
= AllocateAcpiNvsMemoryBelow4G (sizeof (ACPI_CPU_DATA_EX
));
151 AcpiCpuData
= &AcpiCpuDataEx
->AcpuCpuData
;
156 AcpiCpuData
->NumberOfCpus
= 1;
157 AcpiCpuData
->StackSize
= PcdGet32 (PcdCpuApStackSize
);
158 AcpiCpuData
->ApMachineCheckHandlerBase
= 0;
159 AcpiCpuData
->ApMachineCheckHandlerSize
= 0;
160 AcpiCpuData
->GdtrProfile
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->GdtrProfile
;
161 AcpiCpuData
->IdtrProfile
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->IdtrProfile
;
162 AcpiCpuData
->MtrrTable
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->MtrrTable
;
163 AcpiCpuData
->RegisterTable
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->RegisterTable
;
164 AcpiCpuData
->PreSmmInitRegisterTable
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) &AcpiCpuDataEx
->PreSmmInitRegisterTable
;
167 // Allocate stack space for all CPUs
169 AcpiCpuData
->StackAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) AllocateAcpiNvsMemoryBelow4G (AcpiCpuData
->NumberOfCpus
* AcpiCpuData
->StackSize
);
172 // Get MTRR settings from currently executing CPU
174 MtrrGetAllMtrrs (&AcpiCpuDataEx
->MtrrTable
);
177 // Get the BSP's data of GDT and IDT
179 AsmReadGdtr ((IA32_DESCRIPTOR
*) &AcpiCpuDataEx
->GdtrProfile
);
180 AsmReadIdtr ((IA32_DESCRIPTOR
*) &AcpiCpuDataEx
->IdtrProfile
);
183 // Allocate GDT and IDT in ACPI NVS and copy in current GDT and IDT contents
185 GdtSize
= AcpiCpuDataEx
->GdtrProfile
.Limit
+ 1;
186 IdtSize
= AcpiCpuDataEx
->IdtrProfile
.Limit
+ 1;
187 Gdt
= AllocateAcpiNvsMemoryBelow4G (GdtSize
+ IdtSize
);
188 Idt
= (VOID
*)((UINTN
)Gdt
+ GdtSize
);
189 CopyMem (Gdt
, (VOID
*)AcpiCpuDataEx
->GdtrProfile
.Base
, GdtSize
);
190 CopyMem (Idt
, (VOID
*)AcpiCpuDataEx
->IdtrProfile
.Base
, IdtSize
);
191 AcpiCpuDataEx
->GdtrProfile
.Base
= (UINTN
)Gdt
;
192 AcpiCpuDataEx
->IdtrProfile
.Base
= (UINTN
)Idt
;
195 // No RegisterTable entries
197 AcpiCpuDataEx
->RegisterTable
.TableLength
= 0;
200 // No PreSmmInitRegisterTable entries
202 AcpiCpuDataEx
->PreSmmInitRegisterTable
.TableLength
= 0;
205 // Set the base address of CPU S3 data to PcdCpuS3DataAddress
207 Status
= PcdSet64S (PcdCpuS3DataAddress
, (UINT64
)(UINTN
)AcpiCpuData
);
208 ASSERT_EFI_ERROR (Status
);
212 The entry function for QNCInit driver.
214 This function just call initialization function for PciHostBridge,
215 LegacyRegion and QNCSmmAccess module.
217 @param ImageHandle The driver image handle for GmchInit driver
218 @param SystemTable The pointer to System Table
220 @retval EFI_SUCCESS Success to initialize every module for GMCH driver.
221 @return EFI_STATUS The status of initialization work.
227 IN EFI_HANDLE ImageHandle
,
228 IN EFI_SYSTEM_TABLE
*SystemTable
233 S3BootScriptSaveInformationAsciiString (
234 "QNCInitDxeEntryBegin"
237 gQNCInitImageHandle
= ImageHandle
;
239 mQNCDeviceEnables
.Uint32
= PcdGet32 (PcdDeviceEnables
);
243 // Initialize PCIE root ports
245 Status
= QncInitRootPorts ();
246 if (EFI_ERROR (Status
)) {
247 DEBUG ((EFI_D_ERROR
, "QNC Root Port initialization is failed!\n"));
251 Status
= LegacyRegionInit ();
252 if (EFI_ERROR (Status
)) {
253 DEBUG ((EFI_D_ERROR
, "QNC LegacyRegion initialization is failed!\n"));
258 Status
= InitializeQNCPolicy ();
259 if (EFI_ERROR (Status
)) {
260 DEBUG ((EFI_D_ERROR
, "QNC Policy initialization is failed!\n"));
264 Status
= InitializeQNCSmbus (ImageHandle
,SystemTable
);
265 if (EFI_ERROR (Status
)) {
266 DEBUG ((EFI_D_ERROR
, "QNC Smbus driver is failed!\n"));
270 QNCInitializeResource ();
274 S3BootScriptSaveInformationAsciiString (
283 Reserve I/O or memory space in GCD
285 @param IoOrMemory Switch of I/O or memory.
286 @param GcdType Type of the space.
287 @param BaseAddress Base address of the space.
288 @param Length Length of the space.
289 @param Alignment Align with 2^Alignment
290 @param RuntimeOrNot For runtime usage or not
291 @param ImageHandle Handle for the image of this driver.
293 @retval EFI_SUCCESS Reserve successful
296 QNCReserveSpaceInGcd(
299 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
302 IN BOOLEAN RuntimeOrNot
,
303 IN EFI_HANDLE ImageHandle
308 if (IoOrMemory
== QNC_RESERVED_ITEM_MEMORYIO
) {
309 Status
= gDS
->AddMemorySpace (
315 if (EFI_ERROR (Status
)) {
318 "Failed to add memory space :0x%x 0x%x\n",
323 ASSERT_EFI_ERROR (Status
);
324 Status
= gDS
->AllocateMemorySpace (
325 EfiGcdAllocateAddress
,
333 ASSERT_EFI_ERROR (Status
);
335 Status
= gDS
->SetMemorySpaceAttributes (
338 EFI_MEMORY_RUNTIME
| EFI_MEMORY_UC
340 ASSERT_EFI_ERROR (Status
);
343 Status
= gDS
->AddIoSpace (
348 ASSERT_EFI_ERROR (Status
);
349 Status
= gDS
->AllocateIoSpace (
350 EfiGcdAllocateAddress
,
358 ASSERT_EFI_ERROR (Status
);
365 Initialize the memory and io resource which belong to QNC.
366 1) Report and allocate all BAR's memory to GCD.
367 2) Report PCI memory and I/O space to GCD.
368 3) Set memory attribute for <1M memory space.
371 QNCInitializeResource (
374 EFI_PHYSICAL_ADDRESS BaseAddress
;
376 UINT64 ExtraRegionLength
;
377 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
381 // This range maybe has been reportted in PEI phase via Resource Hob.
383 QNCGetTSEGMemoryRange (&BaseAddress
, &ExtraRegionLength
);
384 if (ExtraRegionLength
!= 0) {
385 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &Descriptor
);
386 if (Status
== EFI_NOT_FOUND
) {
387 Status
= gDS
->AddMemorySpace (
388 EfiGcdMemoryTypeReserved
,
397 // < 1M resource setting. The memory ranges <1M has been added into GCD via
398 // resource hob produced by PEI phase. Here will set memory attribute of these
399 // ranges for DXE phase.
403 // Dos Area (0 ~ 0x9FFFFh)
405 Status
= gDS
->GetMemorySpaceDescriptor (0, &Descriptor
);
408 "DOS Area Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",
409 Descriptor
.BaseAddress
,
411 Descriptor
.Attributes
413 ASSERT_EFI_ERROR (Status
);
414 Status
= gDS
->SetMemorySpaceAttributes(
419 ASSERT_EFI_ERROR (Status
);
422 // Default SMRAM UnCachable until SMBASE relocated.
424 Status
= gDS
->SetMemorySpaceAttributes(
429 ASSERT_EFI_ERROR (Status
);
432 // Default SMM ABSEG area. (0xA0000 ~ 0xBFFFF)
434 Status
= gDS
->GetMemorySpaceDescriptor (0xA0000, &Descriptor
);
437 "ABSEG Memory: base = 0x%x, length = 0x%x, attribute = 0x%x\n",
438 Descriptor
.BaseAddress
,
440 Descriptor
.Attributes
442 ASSERT_EFI_ERROR (Status
);
443 Status
= gDS
->SetMemorySpaceAttributes(
448 ASSERT_EFI_ERROR (Status
);
451 // Expansion BIOS area.
453 Status
= gDS
->GetMemorySpaceDescriptor (0xC0000, &Descriptor
);
456 "Memory base = 0x%x, length = 0x%x, attribute = 0x%x\n",
457 Descriptor
.BaseAddress
,
459 Descriptor
.Attributes
461 ASSERT_EFI_ERROR (Status
);
462 Status
= gDS
->SetMemorySpaceAttributes(
467 ASSERT_EFI_ERROR (Status
);
470 // Report other IO resources from mQNCReservedSpaceTable in GCD
472 for (Index
= 0; Index
< sizeof (mQNCReservedSpaceTable
) / sizeof (QNC_SPACE_TABLE_ITEM
); Index
++) {
473 Status
= QNCReserveSpaceInGcd (
474 mQNCReservedSpaceTable
[Index
].IoOrMemory
,
475 mQNCReservedSpaceTable
[Index
].Type
,
476 mQNCReservedSpaceTable
[Index
].BaseAddress
,
477 mQNCReservedSpaceTable
[Index
].Length
,
478 mQNCReservedSpaceTable
[Index
].Alignment
,
479 mQNCReservedSpaceTable
[Index
].RuntimeOrNot
,
482 ASSERT_EFI_ERROR (Status
);
486 // Report unused PCIe config space as reserved.
488 if (PcdGet64 (PcdPciExpressSize
) < SIZE_256MB
) {
489 Status
= QNCReserveSpaceInGcd (
490 QNC_RESERVED_ITEM_MEMORYIO
,
491 EfiGcdMemoryTypeMemoryMappedIo
,
492 (PcdGet64(PcdPciExpressBaseAddress
) + PcdGet64(PcdPciExpressSize
)),
493 (SIZE_256MB
- PcdGet64(PcdPciExpressSize
)),
498 ASSERT_EFI_ERROR (Status
);
503 Use the platform PCD to initialize devices in the QNC
505 @param ImageHandle Handle for the image of this driver.
506 @retval EFI_SUCCESS Initialize successful
509 InitializeQNCPolicy (
512 UINT32 PciD31F0RegBase
; // LPC
514 PciD31F0RegBase
= PciDeviceMmBase (PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_QNC_LPC
, PCI_FUNCTION_NUMBER_QNC_LPC
);
519 if (mQNCDeviceEnables
.Bits
.Smbus
== DXE_DEVICE_DISABLED
) {
520 S3MmioAnd32 (PciD31F0RegBase
+ R_QNC_LPC_SMBUS_BASE
, (~B_QNC_LPC_SMBUS_BASE_EN
));