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