QuarkPlatformPkg/PlatformInit: Fix recovery detection issues
[mirror_edk2.git] / QuarkPlatformPkg / Platform / Pei / PlatformInit / PlatformEarlyInit.c
CommitLineData
b303605e
MK
1/** @file\r
2This PEIM initialize platform for MRC, following action is performed,\r
31. Initizluize GMCH\r
42. Detect boot mode\r
53. Detect video adapter to determine whether we need pre allocated memory\r
64. Calls MRC to initialize memory and install a PPI notify to do post memory initialization.\r
7This file contains the main entrypoint of the PEIM.\r
8\r
406d8575 9Copyright (c) 2013 - 2016 Intel Corporation.\r
b303605e
MK
10\r
11This program and the accompanying materials\r
12are licensed and made available under the terms and conditions of the BSD License\r
13which accompanies this distribution. The full text of the license may be found at\r
14http://opensource.org/licenses/bsd-license.php\r
15\r
16THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
17WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
18\r
19**/\r
20\r
21\r
22#include "CommonHeader.h"\r
23#include "PlatformEarlyInit.h"\r
24#include "PeiFvSecurity.h"\r
25\r
26EFI_STATUS\r
27EFIAPI\r
28EndOfPeiSignalPpiNotifyCallback (\r
29 IN EFI_PEI_SERVICES **PeiServices,\r
30 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
31 IN VOID *Ppi\r
32 );\r
33\r
34//\r
35// Function prototypes to routines implemented in other source modules\r
36// within this component.\r
37//\r
38\r
39EFI_STATUS\r
40EFIAPI\r
41PlatformErratasPostMrc (\r
42 VOID\r
43 );\r
44\r
45//\r
46// The global indicator, the FvFileLoader callback will modify it to TRUE after loading PEIM into memory\r
47//\r
48BOOLEAN ImageInMemory = FALSE;\r
49\r
50BOARD_LEGACY_GPIO_CONFIG mBoardLegacyGpioConfigTable[] = { PLATFORM_LEGACY_GPIO_TABLE_DEFINITION };\r
51UINTN mBoardLegacyGpioConfigTableLen = (sizeof(mBoardLegacyGpioConfigTable) / sizeof(BOARD_LEGACY_GPIO_CONFIG));\r
52BOARD_GPIO_CONTROLLER_CONFIG mBoardGpioControllerConfigTable[] = { PLATFORM_GPIO_CONTROLLER_CONFIG_DEFINITION };\r
53UINTN mBoardGpioControllerConfigTableLen = (sizeof(mBoardGpioControllerConfigTable) / sizeof(BOARD_GPIO_CONTROLLER_CONFIG));\r
54UINT8 ChipsetDefaultMac [6] = {0xff,0xff,0xff,0xff,0xff,0xff};\r
55\r
56EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[1] = {\r
57 {\r
58 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
59 &gEfiPeiMasterBootModePpiGuid,\r
60 NULL\r
61 }\r
62};\r
63\r
64EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = {\r
65 {\r
66 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
67 &gEfiPeiMemoryDiscoveredPpiGuid,\r
68 MemoryDiscoveredPpiNotifyCallback\r
69 }\r
70};\r
71\r
72EFI_PEI_NOTIFY_DESCRIPTOR mEndOfPeiSignalPpiNotifyList[1] = {\r
73 {\r
74 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
75 &gEfiEndOfPeiSignalPpiGuid,\r
76 EndOfPeiSignalPpiNotifyCallback\r
77 }\r
78};\r
79\r
80EFI_PEI_STALL_PPI mStallPpi = {\r
81 PEI_STALL_RESOLUTION,\r
82 Stall\r
83};\r
84\r
85EFI_PEI_PPI_DESCRIPTOR mPpiStall[1] = {\r
86 {\r
87 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
88 &gEfiPeiStallPpiGuid,\r
89 &mStallPpi\r
90 }\r
91};\r
92\r
93/**\r
94 Set Mac address on chipset ethernet device.\r
95\r
96 @param Bus PCI Bus number of chipset ethernet device.\r
97 @param Device Device number of chipset ethernet device.\r
98 @param Func PCI Function number of chipset ethernet device.\r
99 @param MacAddr MAC Address to set.\r
100\r
101**/\r
102VOID\r
103EFIAPI\r
104SetLanControllerMacAddr (\r
105 IN CONST UINT8 Bus,\r
106 IN CONST UINT8 Device,\r
107 IN CONST UINT8 Func,\r
108 IN CONST UINT8 *MacAddr,\r
109 IN CONST UINT32 Bar0\r
110 )\r
111{\r
112 UINT32 Data32;\r
113 UINT16 PciVid;\r
114 UINT16 PciDid;\r
115 UINT32 Addr;\r
116 UINT32 MacVer;\r
117 volatile UINT8 *Wrote;\r
118 UINT32 DevPcieAddr;\r
119 UINT16 SaveCmdReg;\r
120 UINT32 SaveBarReg;\r
121\r
122 DevPcieAddr = PCI_LIB_ADDRESS (\r
123 Bus,\r
124 Device,\r
125 Func,\r
126 0\r
127 );\r
128\r
129 //\r
130 // Do nothing if not a supported device.\r
131 //\r
132 PciVid = PciRead16 (DevPcieAddr + PCI_VENDOR_ID_OFFSET);\r
133 PciDid = PciRead16 (DevPcieAddr + PCI_DEVICE_ID_OFFSET);\r
134 if((PciVid != V_IOH_MAC_VENDOR_ID) || (PciDid != V_IOH_MAC_DEVICE_ID)) {\r
135 return;\r
136 }\r
137\r
138 //\r
139 // Save current settings for PCI CMD/BAR registers\r
140 //\r
141 SaveCmdReg = PciRead16 (DevPcieAddr + PCI_COMMAND_OFFSET);\r
142 SaveBarReg = PciRead32 (DevPcieAddr + R_IOH_MAC_MEMBAR);\r
143\r
144 //\r
145 // Use predefined tempory memory resource\r
146 //\r
147 PciWrite32 ( DevPcieAddr + R_IOH_MAC_MEMBAR, Bar0);\r
148 PciWrite8 ( DevPcieAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);\r
149\r
150 Addr = Bar0 + R_IOH_MAC_GMAC_REG_8;\r
151 MacVer = *((volatile UINT32 *) (UINTN)(Addr));\r
152\r
153 DEBUG ((EFI_D_INFO, "Ioh MAC [B:%d, D:%d, F:%d] VER:%04x ADDR:",\r
154 (UINTN) Bus,\r
155 (UINTN) Device,\r
156 (UINTN) Func,\r
157 (UINTN) MacVer\r
158 ));\r
159\r
160 //\r
161 // Set MAC Address0 Low Register (GMAC_REG_17) ADDRLO bits.\r
162 //\r
163 Addr = Bar0 + R_IOH_MAC_GMAC_REG_17;\r
164 Data32 = *((UINT32 *) (UINTN)(&MacAddr[0]));\r
165 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
166 Wrote = (volatile UINT8 *) (UINTN)(Addr);\r
167 DEBUG ((EFI_D_INFO, "%02x-%02x-%02x-%02x-",\r
168 (UINTN) Wrote[0],\r
169 (UINTN) Wrote[1],\r
170 (UINTN) Wrote[2],\r
171 (UINTN) Wrote[3]\r
172 ));\r
173\r
174 //\r
175 // Set MAC Address0 High Register (GMAC_REG_16) ADDRHI bits\r
176 // and Address Enable (AE) bit.\r
177 //\r
178 Addr = Bar0 + R_IOH_MAC_GMAC_REG_16;\r
179 Data32 =\r
180 ((UINT32) MacAddr[4]) |\r
181 (((UINT32)MacAddr[5]) << 8) |\r
182 B_IOH_MAC_AE;\r
183 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
184 Wrote = (volatile UINT8 *) (UINTN)(Addr);\r
185\r
186 DEBUG ((EFI_D_INFO, "%02x-%02x\n", (UINTN) Wrote[0], (UINTN) Wrote[1]));\r
187\r
188 //\r
189 // Restore settings for PCI CMD/BAR registers\r
190 //\r
191 PciWrite32 ((DevPcieAddr + R_IOH_MAC_MEMBAR), SaveBarReg);\r
192 PciWrite16 (DevPcieAddr + PCI_COMMAND_OFFSET, SaveCmdReg);\r
193}\r
194\r
406d8575
MK
195/**\r
196 Initialize state of I2C GPIO expanders.\r
197\r
198 @param PlatformType Platform type for GPIO expander init.\r
199\r
200**/\r
201EFI_STATUS\r
202EarlyPlatformConfigGpioExpanders (\r
69a0854b
MK
203 IN CONST EFI_PLATFORM_TYPE PlatformType,\r
204 EFI_BOOT_MODE BootMode\r
406d8575
MK
205 )\r
206{\r
207 EFI_STATUS Status;\r
208 EFI_I2C_DEVICE_ADDRESS I2CSlaveAddress;\r
209 UINTN Length;\r
210 UINTN ReadLength;\r
211 UINT8 Buffer[2];\r
212\r
213 //\r
214 // Configure GPIO expanders for Galileo Gen 2\r
215 // Route I2C pins to Arduino header\r
216 // Set all GPIO expander pins connected to the Reset Button as inputs\r
217 //\r
218 if (PlatformType == GalileoGen2) {\r
219 //\r
220 // Configure AMUX1_IN (EXP2.P1_4) as an output\r
221 //\r
222 PlatformPcal9555GpioSetDir (\r
223 GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.\r
224 12, // P1-4.\r
225 FALSE // Configure as output\r
226 );\r
227\r
228 //\r
229 // Set AMUX1_IN(EXP2.P1_4) low to route I2C to Arduino Shield connector\r
230 //\r
231 PlatformPcal9555GpioSetLevel (\r
232 GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.\r
233 12, // P1-4. \r
234 FALSE // Set pin low\r
235 );\r
236\r
237 //\r
238 // Configure Reset Button(EXP1.P1_7) as an input\r
239 //\r
240 PlatformPcal9555GpioSetDir (\r
241 GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR, // IO Expander 1.\r
242 15, // P1-7.\r
243 TRUE\r
244 );\r
245\r
246 //\r
247 // Disable pullup on Reset Button(EXP1.P1_7)\r
248 //\r
249 PlatformPcal9555GpioDisablePull (\r
250 GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR, // IO Expander 1.\r
251 15 // P1-7.\r
252 );\r
253\r
254 //\r
255 // Configure Reset Button(EXP2.P1_7) as an input\r
256 //\r
257 PlatformPcal9555GpioSetDir (\r
258 GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.\r
259 15, // P1-7.\r
260 TRUE\r
261 );\r
262\r
263 //\r
264 // Disable pullup on Reset Button(EXP2.P1_7)\r
265 //\r
266 PlatformPcal9555GpioDisablePull (\r
267 GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2.\r
268 15 // P1-7.\r
269 );\r
69a0854b
MK
270\r
271 if (BootMode != BOOT_IN_RECOVERY_MODE) {\r
272 //\r
273 // Read state of Reset Button - EXP2.P1_7\r
274 // This GPIO is pulled high when the button is not pressed\r
275 // This GPIO reads low when button is pressed\r
276 //\r
277 if (!PlatformPcal9555GpioGetState (\r
278 GALILEO_GEN2_IOEXP2_7BIT_SLAVE_ADDR, // IO Expander 2\r
279 15 // P1-7\r
280 )) {\r
281 DEBUG ((EFI_D_INFO, " Force Recovery mode and reset\n"));\r
282\r
283 //\r
284 // Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset\r
285 //\r
286 QNCAltPortWrite (\r
287 QUARK_SCSS_SOC_UNIT_SB_PORT_ID,\r
288 QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,\r
289 QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW) | B_CFG_STICKY_RW_FORCE_RECOVERY\r
290 );\r
291 ResetWarm();\r
292 }\r
293 }\r
406d8575
MK
294 }\r
295\r
296 //\r
297 // Configure GPIO expanders for Galileo Gen 2\r
298 // Set all GPIO expander pins connected to the Reset Button as inputs\r
299 // Route I2C pins to Arduino header\r
300 //\r
301 if (PlatformType == Galileo) {\r
302 //\r
303 // Detect the I2C Slave Address of the GPIO Expander\r
304 //\r
305 if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {\r
306 I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2HI_7BIT_SLAVE_ADDR;\r
307 } else {\r
308 I2CSlaveAddress.I2CDeviceAddress = GALILEO_IOEXP_J2LO_7BIT_SLAVE_ADDR;\r
309 }\r
310 DEBUG ((EFI_D_INFO, "Galileo GPIO Expender Slave Address = %02x\n", I2CSlaveAddress.I2CDeviceAddress));\r
311\r
312 //\r
313 // Set I2C_MUX (GPORT1_BIT5) low to route I2C to Arduino Shield connector\r
314 //\r
315\r
316 //\r
317 // Select GPIO Expander GPORT1\r
318 //\r
319 Length = 2;\r
320 Buffer[0] = 0x18; //sub-address\r
321 Buffer[1] = 0x01; //data\r
322 Status = I2cWriteMultipleByte (\r
323 I2CSlaveAddress,\r
324 EfiI2CSevenBitAddrMode,\r
325 &Length,\r
326 &Buffer\r
327 );\r
328 ASSERT_EFI_ERROR (Status);\r
329\r
330 //\r
331 // Read "Pin Direction" of GPIO Expander GPORT1\r
332 //\r
333 Length = 1;\r
334 ReadLength = 1;\r
335 Buffer[1] = 0x1C;\r
336 Status = I2cReadMultipleByte (\r
337 I2CSlaveAddress,\r
338 EfiI2CSevenBitAddrMode,\r
339 &Length,\r
340 &ReadLength,\r
341 &Buffer[1]\r
342 );\r
343 ASSERT_EFI_ERROR (Status);\r
344\r
345 //\r
346 // Configure GPIO Expander GPORT1_BIT5 as an output\r
347 //\r
348 Length = 2;\r
349 Buffer[0] = 0x1C; //sub-address\r
350 Buffer[1] = (UINT8)(Buffer[1] & (~BIT5)); //data\r
351\r
352 Status = I2cWriteMultipleByte (\r
353 I2CSlaveAddress,\r
354 EfiI2CSevenBitAddrMode,\r
355 &Length,\r
356 &Buffer\r
357 );\r
358 ASSERT_EFI_ERROR (Status);\r
359\r
360 //\r
361 // Set GPIO Expander GPORT1_BIT5 low\r
362 //\r
363 Length = 2;\r
364 Buffer[0] = 0x09; //sub-address\r
365 Buffer[1] = (UINT8)(~BIT5); //data\r
366\r
367 Status = I2cWriteMultipleByte (\r
368 I2CSlaveAddress,\r
369 EfiI2CSevenBitAddrMode,\r
370 &Length,\r
371 &Buffer\r
372 );\r
373 ASSERT_EFI_ERROR (Status);\r
374\r
375 //\r
376 // Configure RESET_N_SHLD (GPORT5_BIT0) and SW_RESET_N_SHLD (GPORT5_BIT1) as inputs\r
377 //\r
378\r
379 //\r
380 // Select GPIO Expander GPORT5\r
381 //\r
382 Length = 2;\r
383 Buffer[0] = 0x18;\r
384 Buffer[1] = 0x05;\r
385 Status = I2cWriteMultipleByte (\r
386 I2CSlaveAddress,\r
387 EfiI2CSevenBitAddrMode,\r
388 &Length,\r
389 &Buffer\r
390 );\r
391 ASSERT_EFI_ERROR (Status);\r
392\r
393 //\r
394 // Read "Pin Direction" of GPIO Expander GPORT5\r
395 //\r
396 Length = 1;\r
397 ReadLength = 1;\r
398 Buffer[1] = 0x1C;\r
399 Status = I2cReadMultipleByte (\r
400 I2CSlaveAddress,\r
401 EfiI2CSevenBitAddrMode,\r
402 &Length,\r
403 &ReadLength,\r
404 &Buffer[1]\r
405 );\r
406 ASSERT_EFI_ERROR (Status);\r
407\r
408 //\r
409 // Configure GPIO Expander GPORT5_BIT0 and GPORT5_BIT1 as inputs\r
410 //\r
411 Length = 2;\r
412 Buffer[0] = 0x1C;\r
413 Buffer[1] = Buffer[1] | BIT0 | BIT1;\r
414 Status = I2cWriteMultipleByte (\r
415 I2CSlaveAddress,\r
416 EfiI2CSevenBitAddrMode,\r
417 &Length,\r
418 &Buffer\r
419 );\r
420 ASSERT_EFI_ERROR (Status);\r
69a0854b
MK
421\r
422 if (BootMode != BOOT_IN_RECOVERY_MODE) {\r
423 //\r
424 // Read state of RESET_N_SHLD (GPORT5_BIT0)\r
425 //\r
426 Buffer[1] = 5;\r
427 Length = 1;\r
428 ReadLength = 1;\r
429 Status = I2cReadMultipleByte (\r
430 I2CSlaveAddress,\r
431 EfiI2CSevenBitAddrMode,\r
432 &Length,\r
433 &ReadLength,\r
434 &Buffer[1]\r
435 );\r
436 ASSERT_EFI_ERROR (Status);\r
437\r
438 //\r
439 // Return the state of GPORT5_BIT0\r
440 //\r
441 if ((Buffer[1] & BIT0) == 0) {\r
442 DEBUG ((EFI_D_INFO, " Force Recovery mode and reset\n"));\r
443\r
444 //\r
445 // Set 'B_CFG_STICKY_RW_FORCE_RECOVERY' sticky bit so we know we need to do a recovery following warm reset\r
446 //\r
447 QNCAltPortWrite (\r
448 QUARK_SCSS_SOC_UNIT_SB_PORT_ID,\r
449 QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW,\r
450 QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW) | B_CFG_STICKY_RW_FORCE_RECOVERY\r
451 );\r
452 ResetWarm();\r
453 }\r
454 }\r
406d8575
MK
455 }\r
456\r
457 return EFI_SUCCESS;\r
458}\r
459\r
b303605e
MK
460/**\r
461 This is the entrypoint of PEIM\r
462\r
463 @param FileHandle Handle of the file being invoked.\r
464 @param PeiServices Describes the list of possible PEI Services.\r
465\r
466 @retval EFI_SUCCESS if it completed successfully.\r
467**/\r
468EFI_STATUS\r
469EFIAPI\r
470PeiInitPlatform (\r
471 IN EFI_PEI_FILE_HANDLE FileHandle,\r
472 IN CONST EFI_PEI_SERVICES **PeiServices\r
473 )\r
474{\r
475 EFI_STATUS Status;\r
476 EFI_BOOT_MODE BootMode;\r
477 EFI_PEI_STALL_PPI *StallPpi;\r
478 EFI_PEI_PPI_DESCRIPTOR *StallPeiPpiDescriptor;\r
479 EFI_FV_FILE_INFO FileInfo;\r
480 EFI_PLATFORM_TYPE PlatformType;\r
481\r
482 PlatformType = (EFI_PLATFORM_TYPE)PcdGet16 (PcdPlatformType);\r
483\r
484 //\r
485 // Initialize Firmware Volume security.\r
486 // This must be done before any firmware volume accesses (excl. BFV)\r
487 //\r
488 Status = PeiInitializeFvSecurity();\r
489 ASSERT_EFI_ERROR (Status);\r
490\r
491 //\r
492 // Do any early platform specific initialization.\r
493 //\r
494 EarlyPlatformInit ();\r
495\r
496 //\r
497 // This is a second path on entry, in recovery boot path the Stall PPI need to be memory-based\r
498 // to improve recovery performance.\r
499 //\r
500 Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);\r
501 ASSERT_EFI_ERROR (Status);\r
502 //\r
503 // The follow conditional check only works for memory-mapped FFS,\r
504 // so we ASSERT that the file is really a MM FFS.\r
505 //\r
506 ASSERT (FileInfo.Buffer != NULL);\r
507 if (!(((UINTN) FileInfo.Buffer <= (UINTN) PeiInitPlatform) &&\r
508 ((UINTN) PeiInitPlatform <= (UINTN) FileInfo.Buffer + FileInfo.BufferSize))) {\r
509 //\r
510 // Now that module in memory, update the\r
511 // PPI that describes the Stall to other modules\r
512 //\r
513 Status = PeiServicesLocatePpi (\r
514 &gEfiPeiStallPpiGuid,\r
515 0,\r
516 &StallPeiPpiDescriptor,\r
517 (VOID **) &StallPpi\r
518 );\r
519\r
520 if (!EFI_ERROR (Status)) {\r
521\r
522 Status = PeiServicesReInstallPpi (\r
523 StallPeiPpiDescriptor,\r
524 &mPpiStall[0]\r
525 );\r
526 } else {\r
527\r
528 Status = PeiServicesInstallPpi (&mPpiStall[0]);\r
529 }\r
530 return Status;\r
531 }\r
532\r
533 //\r
534 // Initialize System Phys\r
535 //\r
536\r
537 // Program USB Phy\r
538 InitializeUSBPhy();\r
539\r
540 //\r
541 // Do platform specific logic to create a boot mode\r
542 //\r
543 Status = UpdateBootMode ((EFI_PEI_SERVICES**)PeiServices, &BootMode);\r
544 ASSERT_EFI_ERROR (Status);\r
545\r
546 //\r
547 // Signal possible dependent modules that there has been a\r
548 // final boot mode determination\r
549 //\r
550 if (!EFI_ERROR(Status)) {\r
551 Status = PeiServicesInstallPpi (&mPpiBootMode[0]);\r
552 ASSERT_EFI_ERROR (Status);\r
553 }\r
554\r
555 if (BootMode != BOOT_ON_S3_RESUME) {\r
556 QNCClearSmiAndWake ();\r
557 }\r
558\r
559 DEBUG ((EFI_D_INFO, "MRC Entry\n"));\r
560 MemoryInit ((EFI_PEI_SERVICES**)PeiServices);\r
561\r
562 //\r
563 // Do Early PCIe init.\r
564 //\r
565 DEBUG ((EFI_D_INFO, "Early PCIe controller initialization\n"));\r
566 PlatformPciExpressEarlyInit (PlatformType);\r
567\r
568\r
569 DEBUG ((EFI_D_INFO, "Platform Erratas After MRC\n"));\r
570 PlatformErratasPostMrc ();\r
571\r
406d8575
MK
572 //\r
573 //\r
574 //\r
575 DEBUG ((EFI_D_INFO, "EarlyPlatformConfigGpioExpanders ()\n"));\r
69a0854b 576 EarlyPlatformConfigGpioExpanders (PlatformType, BootMode);\r
406d8575 577\r
b303605e
MK
578 //\r
579 // Now that all of the pre-permanent memory activities have\r
580 // been taken care of, post a call-back for the permanent-memory\r
581 // resident services, such as HOB construction.\r
582 // PEI Core will switch stack after this PEIM exit. After that the MTRR\r
583 // can be set.\r
584 //\r
585 Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList[0]);\r
586 ASSERT_EFI_ERROR (Status);\r
587/*\r
588\r
589 if (BootMode != BOOT_ON_S3_RESUME) {\r
590 Status = PeiServicesNotifyPpi (mEndOfPeiSignalPpiNotifyList);\r
591 ASSERT_EFI_ERROR (Status);\r
592 }\r
593*/\r
594 if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
595 PeiServicesRegisterForShadow (FileHandle);\r
596 }\r
597\r
598 return Status;\r
599}\r
600\r
601EFI_STATUS\r
602EFIAPI\r
603EndOfPeiSignalPpiNotifyCallback (\r
604 IN EFI_PEI_SERVICES **PeiServices,\r
605 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
606 IN VOID *Ppi\r
607 )\r
608{\r
609 EFI_STATUS Status;\r
610\r
611 DEBUG ((EFI_D_INFO, "End of PEI Signal Callback\n"));\r
612\r
613 //\r
614 // Restore the flash region to be UC\r
615 // for both normal boot as we build a Resource Hob to\r
616 // describe this region as UC to DXE core.\r
617 //\r
618 WriteBackInvalidateDataCacheRange (\r
619 (VOID *) (UINTN) PcdGet32 (PcdFlashAreaBaseAddress),\r
620 PcdGet32 (PcdFlashAreaSize)\r
621 );\r
622\r
623 Status = MtrrSetMemoryAttribute (PcdGet32 (PcdFlashAreaBaseAddress), PcdGet32 (PcdFlashAreaSize), CacheUncacheable);\r
624 ASSERT_EFI_ERROR (Status);\r
625\r
626 return EFI_SUCCESS;\r
627}\r
628\r
629/**\r
630 This function will initialize USB Phy registers associated with QuarkSouthCluster.\r
631\r
632 @param VOID No Argument\r
633\r
634 @retval EFI_SUCCESS All registers have been initialized\r
635**/\r
636VOID\r
637EFIAPI\r
638InitializeUSBPhy (\r
639 VOID\r
640 )\r
641{\r
642 UINT32 RegData32;\r
643\r
644 /** In order to configure the PHY to use clk120 (ickusbcoreclk) as PLL reference clock\r
645 * and Port2 as a USB device port, the following sequence must be followed\r
646 *\r
647 **/\r
648\r
649 // Sideband register write to USB AFE (Phy)\r
650 RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_GLOBAL_PORT);\r
651 RegData32 &= ~(BIT1);\r
652 //\r
653 // Sighting #4930631 PDNRESCFG [8:7] of USB2_GLOBAL_PORT = 11b.\r
654 // For port 0 & 1 as host and port 2 as device.\r
655 //\r
656 RegData32 |= (BIT8 | BIT7);\r
657 QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_GLOBAL_PORT, RegData32);\r
658\r
659 //\r
660 // Sighting #4930653 Required BIOS change on Disconnect vref to change to 600mV.\r
661 //\r
662 RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_COMPBG);\r
663 RegData32 &= ~(BIT10 | BIT9 | BIT8 | BIT7);\r
664 RegData32 |= (BIT10 | BIT7);\r
665 QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_COMPBG, RegData32);\r
666\r
667 // Sideband register write to USB AFE (Phy)\r
668 // (pllbypass) to bypass/Disable PLL before switch\r
669 RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);\r
670 RegData32 |= BIT29;\r
671 QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);\r
672\r
673 // Sideband register write to USB AFE (Phy)\r
674 // (coreclksel) to select 120MHz (ickusbcoreclk) clk source.\r
675 // (Default 0 to select 96MHz (ickusbclk96_npad/ppad))\r
676 RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1);\r
677 RegData32 |= BIT1;\r
678 QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1, RegData32);\r
679\r
680 // Sideband register write to USB AFE (Phy)\r
681 // (divide by 8) to achieve internal 480MHz clock\r
682 // for 120MHz input refclk. (Default: 4'b1000 (divide by 10) for 96MHz)\r
683 RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1);\r
684 RegData32 &= ~(BIT5 | BIT4 | BIT3);\r
685 RegData32 |= BIT6;\r
686 QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL1, RegData32);\r
687\r
688 // Sideband register write to USB AFE (Phy)\r
689 // Clear (pllbypass)\r
690 RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);\r
691 RegData32 &= ~BIT29;\r
692 QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);\r
693\r
694 // Sideband register write to USB AFE (Phy)\r
695 // Set (startlock) to force the PLL FSM to restart the lock\r
696 // sequence due to input clock/freq switch.\r
697 RegData32 = QNCAltPortRead (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2);\r
698 RegData32 |= BIT24;\r
699 QNCAltPortWrite (QUARK_SC_USB_AFE_SB_PORT_ID, USB2_PLL2, RegData32);\r
700\r
701 // At this point the PLL FSM and COMP FSM will complete\r
702\r
703}\r
704\r
705/**\r
706 This function provides early platform Thermal sensor initialisation.\r
707**/\r
708VOID\r
709EFIAPI\r
710EarlyPlatformThermalSensorInit (\r
711 VOID\r
712 )\r
713{\r
714 DEBUG ((EFI_D_INFO, "Early Platform Thermal Sensor Init\n"));\r
715\r
716 //\r
717 // Set Thermal sensor mode.\r
718 //\r
719 QNCThermalSensorSetRatiometricMode ();\r
720\r
721 //\r
722 // Enable RMU Thermal sensor with a Catastrophic Trip point.\r
723 //\r
724 QNCThermalSensorEnableWithCatastrophicTrip (PLATFORM_CATASTROPHIC_TRIP_CELSIUS);\r
725\r
726 //\r
727 // Lock all RMU Thermal sensor control & trip point registers.\r
728 //\r
729 QNCThermalSensorLockAllRegisters ();\r
730}\r
731\r
732/**\r
733 Print early platform info messages includeing the Stage1 module that's\r
734 running, MFH item list and platform data item list.\r
735**/\r
736VOID\r
737EFIAPI\r
738EarlyPlatformInfoMessages (\r
739 VOID\r
740 )\r
741{\r
742 DEBUG_CODE_BEGIN ();\r
743 QUARK_EDKII_STAGE1_HEADER *Edk2ImageHeader;\r
744\r
745 //\r
746 // Find which 'Stage1' image we are running and print the details\r
747 //\r
748 Edk2ImageHeader = (QUARK_EDKII_STAGE1_HEADER *) PcdGet32 (PcdEsramStage1Base);\r
749 DEBUG ((EFI_D_INFO, "\n************************************************************\n"));\r
750\r
751 switch ((UINT8)Edk2ImageHeader->ImageIndex & QUARK_STAGE1_IMAGE_TYPE_MASK) {\r
752 case QUARK_STAGE1_BOOT_IMAGE_TYPE:\r
753 DEBUG ((EFI_D_INFO, "**** Quark EDKII Stage 1 Boot Image %d ****\n", ((UINT8)Edk2ImageHeader->ImageIndex & ~(QUARK_STAGE1_IMAGE_TYPE_MASK))));\r
754 break;\r
755\r
756 case QUARK_STAGE1_RECOVERY_IMAGE_TYPE:\r
757 DEBUG ((EFI_D_INFO, "**** Quark EDKII Stage 1 Recovery Image %d ****\n", ((UINT8)Edk2ImageHeader->ImageIndex & ~(QUARK_STAGE1_IMAGE_TYPE_MASK))));\r
758 break;\r
759\r
760 default:\r
761 DEBUG ((EFI_D_INFO, "**** Quark EDKII Unknown Stage 1 Image !!!! ****\n"));\r
762 break;\r
763 }\r
764 DEBUG (\r
765 (EFI_D_INFO,\r
766 "**** Quark EDKII Stage 2 Image 0x%08X:0x%08X ****\n" ,\r
767 (UINTN) PcdGet32 (PcdFlashFvMainBase),\r
768 (UINTN) PcdGet32 (PcdFlashFvMainSize)\r
769 ));\r
770\r
771 DEBUG (\r
772 (EFI_D_INFO,\r
773 "**** Quark EDKII Payload Image 0x%08X:0x%08X ****\n" ,\r
774 (UINTN) PcdGet32 (PcdFlashFvPayloadBase),\r
775 (UINTN) PcdGet32 (PcdFlashFvPayloadSize)\r
776 ));\r
777\r
778 DEBUG ((EFI_D_INFO, "************************************************************\n\n"));\r
779\r
780 DEBUG_CODE_END ();\r
781}\r
782\r
783/**\r
784 Check if system reset due to error condition.\r
785\r
786 @param ClearErrorBits If TRUE clear error flags and value bits.\r
787\r
788 @retval TRUE if system reset due to error condition.\r
789 @retval FALSE if NO reset error conditions.\r
790**/\r
791BOOLEAN\r
792CheckForResetDueToErrors (\r
793 IN BOOLEAN ClearErrorBits\r
794 )\r
795{\r
796 UINT32 RegValue;\r
797 BOOLEAN ResetDueToError;\r
798\r
799 ResetDueToError = FALSE;\r
800\r
801 //\r
802 // Check if RMU reset system due to access violations.\r
803 // RMU updates a SOC Unit register before reseting the system.\r
804 //\r
805 RegValue = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW);\r
806 if ((RegValue & B_CFG_STICKY_RW_VIOLATION) != 0) {\r
807 ResetDueToError = TRUE;\r
808\r
809 DEBUG (\r
810 (EFI_D_ERROR,\r
811 "\nReset due to access violation: %s %s %s %s\n",\r
812 ((RegValue & B_CFG_STICKY_RW_IMR_VIOLATION) != 0) ? L"'IMR'" : L".",\r
813 ((RegValue & B_CFG_STICKY_RW_DECC_VIOLATION) != 0) ? L"'DECC'" : L".",\r
814 ((RegValue & B_CFG_STICKY_RW_SMM_VIOLATION) != 0) ? L"'SMM'" : L".",\r
815 ((RegValue & B_CFG_STICKY_RW_HMB_VIOLATION) != 0) ? L"'HMB'" : L"."\r
816 ));\r
817\r
818 //\r
819 // Clear error bits.\r
820 //\r
821 if (ClearErrorBits) {\r
822 RegValue &= ~(B_CFG_STICKY_RW_VIOLATION);\r
823 QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_CFG_STICKY_RW, RegValue);\r
824 }\r
825 }\r
826\r
827 return ResetDueToError;\r
828}\r
829\r
830/**\r
831 This function provides early platform initialization.\r
832\r
833 @param PlatformInfo Pointer to platform Info structure.\r
834\r
835**/\r
836VOID\r
837EFIAPI\r
838EarlyPlatformInit (\r
839 VOID\r
840 )\r
841{\r
842 EFI_PLATFORM_TYPE PlatformType;\r
843\r
844 PlatformType = (EFI_PLATFORM_TYPE) PcdGet16 (PcdPlatformType);\r
845\r
846 DEBUG ((EFI_D_INFO, "EarlyPlatformInit for PlatType=0x%02x\n", (UINTN) PlatformType));\r
847\r
848 //\r
849 // Check if system reset due to error condition.\r
850 //\r
851 if (CheckForResetDueToErrors (TRUE)) {\r
852 if(FeaturePcdGet (WaitIfResetDueToError)) {\r
69a0854b
MK
853 DEBUG ((EFI_D_ERROR, "Wait 10 seconds.\n"));\r
854 MicroSecondDelay(10000000);\r
b303605e
MK
855 }\r
856 }\r
857\r
858 //\r
859 // Display platform info messages.\r
860 //\r
861 EarlyPlatformInfoMessages ();\r
862\r
863 //\r
864 // Early Legacy Gpio Init.\r
865 //\r
866 EarlyPlatformLegacyGpioInit (PlatformType);\r
867\r
868 //\r
869 // Early platform Legacy GPIO manipulation depending on GPIOs\r
870 // setup by EarlyPlatformLegacyGpioInit.\r
871 //\r
872 EarlyPlatformLegacyGpioManipulation (PlatformType);\r
873\r
874 //\r
875 // Early platform specific GPIO Controller init & manipulation.\r
876 // Combined for sharing of temp. memory bar.\r
877 //\r
878 EarlyPlatformGpioCtrlerInitAndManipulation (PlatformType);\r
879\r
880 //\r
881 // Early Thermal Sensor Init.\r
882 //\r
883 EarlyPlatformThermalSensorInit ();\r
884\r
885 //\r
886 // Early Lan Ethernet Mac Init.\r
887 //\r
888 EarlyPlatformMacInit (\r
889 PcdGetPtr (PcdIohEthernetMac0),\r
890 PcdGetPtr (PcdIohEthernetMac1)\r
891 );\r
892}\r
893\r
894/**\r
895 This function provides early platform Legacy GPIO initialisation.\r
896\r
897 @param PlatformType Platform type for GPIO init.\r
898\r
899**/\r
900VOID\r
901EFIAPI\r
902EarlyPlatformLegacyGpioInit (\r
903 IN CONST EFI_PLATFORM_TYPE PlatformType\r
904 )\r
905{\r
906 BOARD_LEGACY_GPIO_CONFIG *LegacyGpioConfig;\r
907 UINT32 NewValue;\r
908 UINT32 GpioBaseAddress;\r
909\r
910 //\r
911 // Assert if platform type outside table range.\r
912 //\r
913 ASSERT ((UINTN) PlatformType < mBoardLegacyGpioConfigTableLen);\r
914 LegacyGpioConfig = &mBoardLegacyGpioConfigTable[(UINTN) PlatformType];\r
915\r
916 GpioBaseAddress = (UINT32)PcdGet16 (PcdGbaIoBaseAddress);\r
917\r
918 NewValue = 0x0;\r
919 //\r
920 // Program QNC GPIO Registers.\r
921 //\r
922 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGEN_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellEnable;\r
923 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGEN_CORE_WELL, NewValue );\r
924 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGIO_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellIoSelect;\r
925 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGIO_CORE_WELL, NewValue);\r
926 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGLVL_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellLvlForInputOrOutput;\r
927 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGLVL_CORE_WELL, NewValue);\r
928 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTPE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerPositiveEdge;\r
929 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTPE_CORE_WELL, NewValue );\r
930 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTNE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerNegativeEdge;\r
931 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTNE_CORE_WELL, NewValue);\r
932 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGGPE_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellGPEEnable;\r
933 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGGPE_CORE_WELL, NewValue);\r
934 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGSMI_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellSMIEnable;\r
935 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGSMI_CORE_WELL, NewValue );\r
936 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CGTS_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellTriggerStatus;\r
937 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CGTS_CORE_WELL, NewValue);\r
938 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_CNMIEN_CORE_WELL) & 0xFFFFFFFC) | LegacyGpioConfig->CoreWellNMIEnable;\r
939 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_CNMIEN_CORE_WELL, NewValue);\r
940\r
941 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGEN_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellEnable;\r
942 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGEN_RESUME_WELL, NewValue );\r
943 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGIO_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellIoSelect;\r
944 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGIO_RESUME_WELL, NewValue) ;\r
945 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellLvlForInputOrOutput;\r
946 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL, NewValue);\r
947 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTPE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerPositiveEdge;\r
948 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTPE_RESUME_WELL, NewValue );\r
949 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTNE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerNegativeEdge;\r
950 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTNE_RESUME_WELL, NewValue) ;\r
951 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGGPE_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellGPEEnable;\r
952 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGGPE_RESUME_WELL, NewValue);\r
953 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGSMI_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellSMIEnable;\r
954 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGSMI_RESUME_WELL, NewValue );\r
955 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RGTS_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellTriggerStatus;\r
956 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGTS_RESUME_WELL, NewValue) ;\r
957 NewValue = (IoRead32 (GpioBaseAddress + R_QNC_GPIO_RNMIEN_RESUME_WELL) & 0xFFFFFFC0) | LegacyGpioConfig->ResumeWellNMIEnable;\r
958 IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RNMIEN_RESUME_WELL, NewValue);\r
959}\r
960\r
961/**\r
962 Performs any early platform specific Legacy GPIO manipulation.\r
963\r
964 @param PlatformType Platform type GPIO manipulation.\r
965\r
966**/\r
967VOID\r
968EFIAPI\r
969EarlyPlatformLegacyGpioManipulation (\r
970 IN CONST EFI_PLATFORM_TYPE PlatformType\r
971 )\r
972{\r
973 if (PlatformType == CrossHill) {\r
974\r
975 //\r
976 // Pull TPM reset low for 80us (equivalent to cold reset, Table 39\r
977 // Infineon SLB9645 Databook), then pull TPM reset high and wait for\r
978 // 150ms to give time for TPM to stabilise (Section 4.7.1 Infineon\r
979 // SLB9645 Databook states TPM is ready to receive command after 30ms\r
980 // but section 4.7 states some TPM commands may take longer to execute\r
981 // upto 150ms after test).\r
982 //\r
983\r
984 PlatformLegacyGpioSetLevel (\r
985 R_QNC_GPIO_RGLVL_RESUME_WELL,\r
986 PLATFORM_RESUMEWELL_TPM_RST_GPIO,\r
987 FALSE\r
988 );\r
989 MicroSecondDelay (80);\r
990\r
991 PlatformLegacyGpioSetLevel (\r
992 R_QNC_GPIO_RGLVL_RESUME_WELL,\r
993 PLATFORM_RESUMEWELL_TPM_RST_GPIO,\r
994 TRUE\r
995 );\r
996 MicroSecondDelay (150000);\r
997 }\r
998\r
999}\r
1000\r
1001/**\r
1002 Performs any early platform specific GPIO Controller init & manipulation.\r
1003\r
1004 @param PlatformType Platform type for GPIO init & manipulation.\r
1005\r
1006**/\r
1007VOID\r
1008EFIAPI\r
1009EarlyPlatformGpioCtrlerInitAndManipulation (\r
1010 IN CONST EFI_PLATFORM_TYPE PlatformType\r
1011 )\r
1012{\r
1013 UINT32 IohGpioBase;\r
1014 UINT32 Data32;\r
1015 UINT32 Addr;\r
1016 BOARD_GPIO_CONTROLLER_CONFIG *GpioConfig;\r
1017 UINT32 DevPcieAddr;\r
1018 UINT16 SaveCmdReg;\r
1019 UINT32 SaveBarReg;\r
1020 UINT16 PciVid;\r
1021 UINT16 PciDid;\r
1022\r
1023 ASSERT ((UINTN) PlatformType < mBoardGpioControllerConfigTableLen);\r
1024 GpioConfig = &mBoardGpioControllerConfigTable[(UINTN) PlatformType];\r
1025\r
1026 IohGpioBase = (UINT32) PcdGet64 (PcdIohGpioMmioBase);\r
1027\r
1028 DevPcieAddr = PCI_LIB_ADDRESS (\r
1029 PcdGet8 (PcdIohGpioBusNumber),\r
1030 PcdGet8 (PcdIohGpioDevNumber),\r
1031 PcdGet8 (PcdIohGpioFunctionNumber),\r
1032 0\r
1033 );\r
1034\r
1035 //\r
1036 // Do nothing if not a supported device.\r
1037 //\r
1038 PciVid = PciRead16 (DevPcieAddr + PCI_VENDOR_ID_OFFSET);\r
1039 PciDid = PciRead16 (DevPcieAddr + PCI_DEVICE_ID_OFFSET);\r
1040 if((PciVid != V_IOH_I2C_GPIO_VENDOR_ID) || (PciDid != V_IOH_I2C_GPIO_DEVICE_ID)) {\r
1041 return;\r
1042 }\r
1043\r
1044 //\r
1045 // Save current settings for PCI CMD/BAR registers.\r
1046 //\r
1047 SaveCmdReg = PciRead16 (DevPcieAddr + PCI_COMMAND_OFFSET);\r
1048 SaveBarReg = PciRead32 (DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister));\r
1049\r
1050 //\r
1051 // Use predefined tempory memory resource.\r
1052 //\r
1053 PciWrite32 ( DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister), IohGpioBase);\r
1054 PciWrite8 ( DevPcieAddr + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);\r
1055\r
1056 //\r
1057 // Gpio Controller Init Tasks.\r
1058 //\r
1059\r
1060 //\r
1061 // IEN- Interrupt Enable Register\r
1062 //\r
1063 Addr = IohGpioBase + GPIO_INTEN;\r
1064 Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]\r
1065 Data32 |= (GpioConfig->IntEn & 0x000FFFFF);\r
1066 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1067\r
1068 //\r
1069 // ISTATUS- Interrupt Status Register\r
1070 //\r
1071 Addr = IohGpioBase + GPIO_INTSTATUS;\r
1072 Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]\r
1073 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1074\r
1075 //\r
1076 // GPIO SWPORTA Direction Register - GPIO_SWPORTA_DR\r
1077 //\r
1078 Addr = IohGpioBase + GPIO_SWPORTA_DR;\r
1079 Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]\r
1080 Data32 |= (GpioConfig->PortADR & 0x000FFFFF);\r
1081 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1082\r
1083 //\r
1084 // GPIO SWPORTA Data Direction Register - GPIO_SWPORTA_DDR - default input\r
1085 //\r
1086 Addr = IohGpioBase + GPIO_SWPORTA_DDR;\r
1087 Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]\r
1088 Data32 |= (GpioConfig->PortADir & 0x000FFFFF);\r
1089 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1090\r
1091 //\r
1092 // Interrupt Mask Register - GPIO_INTMASK - default interrupts unmasked\r
1093 //\r
1094 Addr = IohGpioBase + GPIO_INTMASK;\r
1095 Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]\r
1096 Data32 |= (GpioConfig->IntMask & 0x000FFFFF);\r
1097 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1098\r
1099 //\r
1100 // Interrupt Level Type Register - GPIO_INTTYPE_LEVEL - default is level sensitive\r
1101 //\r
1102 Addr = IohGpioBase + GPIO_INTTYPE_LEVEL;\r
1103 Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]\r
1104 Data32 |= (GpioConfig->IntType & 0x000FFFFF);\r
1105 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1106\r
1107 //\r
1108 // Interrupt Polarity Type Register - GPIO_INT_POLARITY - default is active low\r
1109 //\r
1110 Addr = IohGpioBase + GPIO_INT_POLARITY;\r
1111 Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]\r
1112 Data32 |= (GpioConfig->IntPolarity & 0x000FFFFF);\r
1113 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1114\r
1115 //\r
1116 // Interrupt Debounce Type Register - GPIO_DEBOUNCE - default no debounce\r
1117 //\r
1118 Addr = IohGpioBase + GPIO_DEBOUNCE;\r
1119 Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]\r
1120 Data32 |= (GpioConfig->Debounce & 0x000FFFFF);\r
1121 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1122\r
1123 //\r
1124 // Interrupt Clock Synchronisation Register - GPIO_LS_SYNC - default no sync with pclk_intr(APB bus clk)\r
1125 //\r
1126 Addr = IohGpioBase + GPIO_LS_SYNC;\r
1127 Data32 = *((volatile UINT32 *) (UINTN)(Addr)) & 0xFFFFFF00; // Keep reserved bits [31:8]\r
1128 Data32 |= (GpioConfig->LsSync & 0x000FFFFF);\r
1129 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1130\r
1131 //\r
1132 // Gpio Controller Manipulation Tasks.\r
1133 //\r
1134\r
1135 if (PlatformType == (EFI_PLATFORM_TYPE) Galileo) {\r
1136 //\r
1137 // Reset Cypress Expander on Galileo Platform\r
1138 //\r
1139 Addr = IohGpioBase + GPIO_SWPORTA_DR;\r
1140 Data32 = *((volatile UINT32 *) (UINTN)(Addr));\r
1141 Data32 |= BIT4; // Cypress Reset line controlled by GPIO<4>\r
1142 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1143\r
1144 Data32 = *((volatile UINT32 *) (UINTN)(Addr));\r
1145 Data32 &= ~BIT4; // Cypress Reset line controlled by GPIO<4>\r
1146 *((volatile UINT32 *) (UINTN)(Addr)) = Data32;\r
1147\r
1148 }\r
1149\r
1150 //\r
1151 // Restore settings for PCI CMD/BAR registers\r
1152 //\r
1153 PciWrite32 ((DevPcieAddr + PcdGet8 (PcdIohGpioBarRegister)), SaveBarReg);\r
1154 PciWrite16 (DevPcieAddr + PCI_COMMAND_OFFSET, SaveCmdReg);\r
1155}\r
1156\r
1157/**\r
1158 Performs any early platform init of SoC Ethernet Mac devices.\r
1159\r
1160 @param IohMac0Address Mac address to program into Mac0 device.\r
1161 @param IohMac1Address Mac address to program into Mac1 device.\r
1162\r
1163**/\r
1164VOID\r
1165EFIAPI\r
1166EarlyPlatformMacInit (\r
1167 IN CONST UINT8 *IohMac0Address,\r
1168 IN CONST UINT8 *IohMac1Address\r
1169 )\r
1170{\r
1171 BOOLEAN SetMacAddr;\r
1172\r
1173 //\r
1174 // Set chipset MAC0 address if configured.\r
1175 //\r
1176 SetMacAddr =\r
1177 (CompareMem (ChipsetDefaultMac, IohMac0Address, sizeof (ChipsetDefaultMac))) != 0;\r
1178 if (SetMacAddr) {\r
1179 if ((*(IohMac0Address) & BIT0) != 0) {\r
1180 DEBUG ((EFI_D_ERROR, "HALT: Multicast Mac Address configured for Ioh MAC [B:%d, D:%d, F:%d]\n",\r
1181 (UINTN) IOH_MAC0_BUS_NUMBER,\r
1182 (UINTN) IOH_MAC0_DEVICE_NUMBER,\r
1183 (UINTN) IOH_MAC0_FUNCTION_NUMBER\r
1184 ));\r
1185 ASSERT (FALSE);\r
1186 } else {\r
1187 SetLanControllerMacAddr (\r
1188 IOH_MAC0_BUS_NUMBER,\r
1189 IOH_MAC0_DEVICE_NUMBER,\r
1190 IOH_MAC0_FUNCTION_NUMBER,\r
1191 IohMac0Address,\r
1192 (UINT32) PcdGet64(PcdIohMac0MmioBase)\r
1193 );\r
1194 }\r
1195 } else {\r
1196 DEBUG ((EFI_D_WARN, "WARNING: Ioh MAC [B:%d, D:%d, F:%d] NO HW ADDR CONFIGURED!!!\n",\r
1197 (UINTN) IOH_MAC0_BUS_NUMBER,\r
1198 (UINTN) IOH_MAC0_DEVICE_NUMBER,\r
1199 (UINTN) IOH_MAC0_FUNCTION_NUMBER\r
1200 ));\r
1201 }\r
1202\r
1203 //\r
1204 // Set chipset MAC1 address if configured.\r
1205 //\r
1206 SetMacAddr =\r
1207 (CompareMem (ChipsetDefaultMac, IohMac1Address, sizeof (ChipsetDefaultMac))) != 0;\r
1208 if (SetMacAddr) {\r
1209 if ((*(IohMac1Address) & BIT0) != 0) {\r
1210 DEBUG ((EFI_D_ERROR, "HALT: Multicast Mac Address configured for Ioh MAC [B:%d, D:%d, F:%d]\n",\r
1211 (UINTN) IOH_MAC1_BUS_NUMBER,\r
1212 (UINTN) IOH_MAC1_DEVICE_NUMBER,\r
1213 (UINTN) IOH_MAC1_FUNCTION_NUMBER\r
1214 ));\r
1215 ASSERT (FALSE);\r
1216 } else {\r
1217 SetLanControllerMacAddr (\r
1218 IOH_MAC1_BUS_NUMBER,\r
1219 IOH_MAC1_DEVICE_NUMBER,\r
1220 IOH_MAC1_FUNCTION_NUMBER,\r
1221 IohMac1Address,\r
1222 (UINT32) PcdGet64(PcdIohMac1MmioBase)\r
1223 );\r
1224 }\r
1225 } else {\r
1226 DEBUG ((EFI_D_WARN, "WARNING: Ioh MAC [B:%d, D:%d, F:%d] NO HW ADDR CONFIGURED!!!\n",\r
1227 (UINTN) IOH_MAC1_BUS_NUMBER,\r
1228 (UINTN) IOH_MAC1_DEVICE_NUMBER,\r
1229 (UINTN) IOH_MAC1_FUNCTION_NUMBER\r
1230 ));\r
1231 }\r
1232}\r
1233\r