/** @file Copyright (c) 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "UpXtremeInit.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /// /// Reset Generator I/O Port /// #define RESET_GENERATOR_PORT 0xCF9 typedef struct { EFI_PHYSICAL_ADDRESS BaseAddress; UINT64 Length; } MEMORY_MAP; GLOBAL_REMOVE_IF_UNREFERENCED MEMORY_MAP MmioMap[] = { { FixedPcdGet64(PcdApicLocalAddress), FixedPcdGet32(PcdApicLocalMmioSize) }, { FixedPcdGet64(PcdMchBaseAddress), FixedPcdGet32(PcdMchMmioSize) }, { FixedPcdGet64(PcdDmiBaseAddress), FixedPcdGet32(PcdDmiMmioSize) }, { FixedPcdGet64(PcdEpBaseAddress), FixedPcdGet32(PcdEpMmioSize) }, { FixedPcdGet64(PcdGdxcBaseAddress), FixedPcdGet32(PcdGdxcMmioSize) } }; EFI_STATUS MrcConfigInit( IN UINT16 BoardId ); EFI_STATUS SaGpioConfigInit( IN UINT16 BoardId ); EFI_STATUS SaMiscConfigInit( IN UINT16 BoardId ); EFI_STATUS RootPortClkInfoInit( IN UINT16 BoardId ); EFI_STATUS UsbConfigInit( IN UINT16 BoardId ); EFI_STATUS GpioGroupTierInit( IN UINT16 BoardId ); EFI_STATUS GpioTablePreMemInit( IN UINT16 BoardId ); EFI_STATUS PchPmConfigInit( IN UINT16 BoardId ); EFI_STATUS SaDisplayConfigInit( IN UINT16 BoardId ); EFI_STATUS EFIAPI PlatformInitPreMemCallBack( IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ); EFI_STATUS EFIAPI MemoryDiscoveredPpiNotify( IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ); EFI_STATUS EFIAPI PchReset( IN CONST EFI_PEI_SERVICES **PeiServices ); static EFI_PEI_RESET_PPI mResetPpi = { PchReset }; static EFI_PEI_PPI_DESCRIPTOR mPreMemPpiList[] = { { (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gEfiPeiResetPpiGuid, &mResetPpi } }; static EFI_PEI_NOTIFY_DESCRIPTOR mPreMemNotifyList = { (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gEfiPeiReadOnlyVariable2PpiGuid, (EFI_PEIM_NOTIFY_ENTRY_POINT)PlatformInitPreMemCallBack }; static EFI_PEI_NOTIFY_DESCRIPTOR mMemDiscoveredNotifyList = { (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gEfiPeiMemoryDiscoveredPpiGuid, (EFI_PEIM_NOTIFY_ENTRY_POINT)MemoryDiscoveredPpiNotify }; /** Board misc init function for PEI pre-memory phase. @param[in] BoardId An unsigned integer represent the board id. @retval EFI_SUCCESS The function completed successfully. **/ EFI_STATUS BoardMiscInitPreMem( IN UINT16 BoardId ) { // // Configure WWAN Full Card Power Off and reset pins // switch (BoardId) { // todo for UP Xtreme case BoardIdWhiskeyLakeRvp: // // According to board default settings, GPP_D16 is used to enable/disable modem // power. An alternative way to contol modem power is to toggle FCP_OFF via GPP_D13 // but board rework is required. // PcdSet32S (PcdWwanFullCardPowerOffGpio, GPIO_CNL_LP_GPP_D16); PcdSet32S (PcdWwanBbrstGpio, GPIO_CNL_LP_GPP_F1); PcdSet32S (PcdWwanPerstGpio, GPIO_CNL_LP_GPP_E15); PcdSet8S (PcdWwanPerstGpioPolarity, 1); break; default: break; } // // Pc8374SioKbc Present // PcdSetBoolS (PcdPc8374SioKbcPresent, FALSE); return EFI_SUCCESS; } //@todo it should be moved to Si Pkg. /** Early Platform PCH initialization **/ VOID EarlyPlatformPchInit( VOID ) { UINT8 Data8; UINT16 Data16; UINT8 TcoRebootHappened; TCO_WDT_HOB *TcoWdtHobPtr; EFI_STATUS Status; /// /// Halt the TCO timer /// Data16 = IoRead16 (PcdGet16 (PcdTcoBaseAddress) + R_TCO_IO_TCO1_CNT); Data16 |= B_TCO_IO_TCO1_CNT_TMR_HLT; IoWrite16 (PcdGet16 (PcdTcoBaseAddress) + R_TCO_IO_TCO1_CNT, Data16); /// /// Read the Second TO status bit /// Data8 = IoRead8 (PcdGet16 (PcdTcoBaseAddress) + R_TCO_IO_TCO2_STS); if ((Data8 & B_TCO_IO_TCO2_STS_SECOND_TO) == B_TCO_IO_TCO2_STS_SECOND_TO) { TcoRebootHappened = 1; DEBUG ((DEBUG_INFO, "PlatformInitPreMem - TCO Second TO status bit is set. This might be a TCO reboot\n")); } else { TcoRebootHappened = 0; } /// /// Create HOB /// Status = PeiServicesCreateHob (EFI_HOB_TYPE_GUID_EXTENSION, sizeof (TCO_WDT_HOB), (VOID **) &TcoWdtHobPtr); if (!EFI_ERROR (Status)) { TcoWdtHobPtr->Header.Name = gTcoWdtHobGuid; TcoWdtHobPtr->TcoRebootHappened = TcoRebootHappened; } /// /// Clear the Second TO status bit /// IoWrite8 (PcdGet16(PcdTcoBaseAddress) + R_TCO_IO_TCO2_STS, B_TCO_IO_TCO2_STS_SECOND_TO); } /** Board configuration initialization in the pre-memory boot phase. **/ VOID BoardConfigInitPreMem ( VOID ) { EFI_STATUS Status; UINT16 BoardId; BoardId = BoardIdUpXtreme; Status = MrcConfigInit (BoardId); ASSERT_EFI_ERROR (Status); Status = SaGpioConfigInit (BoardId); ASSERT_EFI_ERROR (Status); Status = SaMiscConfigInit (BoardId); ASSERT_EFI_ERROR (Status); Status = RootPortClkInfoInit (BoardId); ASSERT_EFI_ERROR (Status); Status = UsbConfigInit (BoardId); ASSERT_EFI_ERROR (Status); Status = GpioGroupTierInit (BoardId); ASSERT_EFI_ERROR (Status); Status = GpioTablePreMemInit (BoardId); ASSERT_EFI_ERROR (Status); Status = PchPmConfigInit (BoardId); ASSERT_EFI_ERROR (Status); Status = BoardMiscInitPreMem (BoardId); ASSERT_EFI_ERROR (Status); Status = SaDisplayConfigInit (BoardId); ASSERT_EFI_ERROR (Status); } /** This function handles PlatformInit task after PeiReadOnlyVariable2 PPI produced @param[in] PeiServices Pointer to PEI Services Table. @param[in] NotifyDesc Pointer to the descriptor for the Notification event that caused this function to execute. @param[in] Ppi Pointer to the PPI data associated with this function. @retval EFI_SUCCESS The function completes successfully @retval others **/ EFI_STATUS EFIAPI PlatformInitPreMemCallBack( IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; UINT16 ABase; UINT8 FwConfig; // // Init Board Config Pcd. // BoardConfigInitPreMem (); FwConfig = FwConfigProduction; PcdSetBoolS (PcdPcieWwanEnable, FALSE); PcdSetBoolS (PcdWwanResetWorkaround, FALSE); // // Early Board Configuration before memory is ready. // Status = BoardInitEarlyPreMem (); ASSERT_EFI_ERROR (Status); /// /// If there was unexpected reset but no WDT expiration and no resume from S3/S4, /// clear unexpected reset status and enforce expiration. This is to inform Firmware /// which has no access to unexpected reset status bit, that something went wrong. /// OcWdtResetCheck (); Status = OcWdtInit (); ASSERT_EFI_ERROR (Status); // // Initialize Intel PEI Platform Policy // PeiPolicyInitPreMem (FwConfig); /// /// Configure GPIO and SIO /// Status = BoardInitPreMem (); ASSERT_EFI_ERROR (Status); ABase = PmcGetAcpiBase (); /// /// Clear all pending SMI. On S3 clear power button enable so it will not generate an SMI. /// IoWrite16 (ABase + R_ACPI_IO_PM1_EN, 0); IoWrite32 (ABase + R_ACPI_IO_GPE0_EN_127_96, 0); /// /// Install Pre Memory PPIs /// Status = PeiServicesInstallPpi (&mPreMemPpiList[0]); ASSERT_EFI_ERROR (Status); return Status; } /** Provide hard reset PPI service. To generate full hard reset, write 0x0E to PCH RESET_GENERATOR_PORT (0xCF9). @param[in] PeiServices General purpose services available to every PEIM. @retval Not return System reset occured. @retval EFI_DEVICE_ERROR Device error, could not reset the system. **/ EFI_STATUS EFIAPI PchReset( IN CONST EFI_PEI_SERVICES **PeiServices ) { DEBUG ((DEBUG_INFO, "Perform Cold Reset\n")); IoWrite8 (RESET_GENERATOR_PORT, 0x0E); CpuDeadLoop (); /// /// System reset occured, should never reach at this line. /// ASSERT_EFI_ERROR (EFI_DEVICE_ERROR); return EFI_DEVICE_ERROR; } /** Install Firmware Volume Hob's once there is main memory @param[in] PeiServices General purpose services available to every PEIM. @param[in] NotifyDescriptor Notify that this module published. @param[in] Ppi PPI that was installed. @retval EFI_SUCCESS The function completed successfully. **/ EFI_STATUS EFIAPI MemoryDiscoveredPpiNotify( IN CONST EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; UINTN Index; UINT8 PhysicalAddressBits; UINT32 RegEax; MEMORY_MAP PcieMmioMap; Index = 0; Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000008) { AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); PhysicalAddressBits = (UINT8) RegEax; } else { PhysicalAddressBits = 36; } /// /// Create a CPU hand-off information /// BuildCpuHob (PhysicalAddressBits, 16); /// /// Build Memory Mapped IO Resource which is used to build E820 Table in LegacyBios. /// PcieMmioMap.BaseAddress = FixedPcdGet64 (PcdPciExpressBaseAddress); PcieMmioMap.Length = PcdGet32 (PcdPciExpressRegionLength); BuildResourceDescriptorHob ( EFI_RESOURCE_MEMORY_MAPPED_IO, (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), PcieMmioMap.BaseAddress, PcieMmioMap.Length ); BuildMemoryAllocationHob ( PcieMmioMap.BaseAddress, PcieMmioMap.Length, EfiMemoryMappedIO ); for (Index = 0; Index < sizeof (MmioMap) / (sizeof (MEMORY_MAP)); Index++) { BuildResourceDescriptorHob ( EFI_RESOURCE_MEMORY_MAPPED_IO, (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), MmioMap[Index].BaseAddress, MmioMap[Index].Length ); BuildMemoryAllocationHob ( MmioMap[Index].BaseAddress, MmioMap[Index].Length, EfiMemoryMappedIO ); } // // Report resource HOB for flash FV // BuildResourceDescriptorHob ( EFI_RESOURCE_MEMORY_MAPPED_IO, (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), (UINTN) FixedPcdGet32 (PcdFlashAreaBaseAddress), (UINTN) FixedPcdGet32 (PcdFlashAreaSize) ); BuildMemoryAllocationHob ( (UINTN) FixedPcdGet32 (PcdFlashAreaBaseAddress), (UINTN) FixedPcdGet32 (PcdFlashAreaSize), EfiMemoryMappedIO ); BuildFvHob ( (UINTN) FixedPcdGet32 (PcdFlashAreaBaseAddress), (UINTN) FixedPcdGet32 (PcdFlashAreaSize) ); return Status; } /** Board configuration init function for PEI pre-memory phase. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER The parameter is NULL. **/ EFI_STATUS EFIAPI UpXtremeInitPreMem ( VOID ) { EFI_STATUS Status; /// /// Install Stall PPI /// Status = InstallStallPpi (); ASSERT_EFI_ERROR (Status); ///@todo it should be moved to Si Pkg. /// /// Do Early PCH init /// EarlyPlatformPchInit (); // // Install PCH RESET PPI and EFI RESET2 PeiService // Status = PchInitializeReset (); ASSERT_EFI_ERROR (Status); /// /// Performing PlatformInitPreMemCallBack after PeiReadOnlyVariable2 PPI produced /// Status = PeiServicesNotifyPpi (&mPreMemNotifyList); /// /// After code reorangized, memorycallback will run because the PPI is already /// installed when code run to here, it is supposed that the InstallEfiMemory is /// done before. /// Status = PeiServicesNotifyPpi (&mMemDiscoveredNotifyList); return EFI_SUCCESS; } /** Configure GPIO and SIO before memory ready @retval EFI_SUCCESS Operation success. **/ EFI_STATUS EFIAPI UpXtremeBoardInitBeforeMemoryInit ( VOID ) { UpXtremeInitPreMem (); return EFI_SUCCESS; } EFI_STATUS EFIAPI UpXtremeBoardDebugInit ( VOID ) { // Serial port initialization is performed in the PlatformHookSerialPortInitialize () // function invoked by SerialPortInitialize () in SerialPortLib DEBUG_CODE_BEGIN(); DEBUG_CONFIG_DATA_HOB *DebugConfigDataHob; DebugConfigDataHob = BuildGuidHob (&gDebugConfigHobGuid, sizeof (DEBUG_CONFIG_DATA_HOB)); ASSERT (DebugConfigDataHob != NULL); if (DebugConfigDataHob == NULL) { DEBUG ((DEBUG_ERROR, "Build Debug Config Hob failed!\n")); return EFI_OUT_OF_RESOURCES; } switch (PcdGet32 (PcdSerialBaudRate)) { case 9600: DebugConfigDataHob->SerialDebugBaudRate = 3; break; case 19200: DebugConfigDataHob->SerialDebugBaudRate = 4; break; case 57600: DebugConfigDataHob->SerialDebugBaudRate = 6; break; default: DebugConfigDataHob->SerialDebugBaudRate = 7; } DebugConfigDataHob->SerialDebug = 0x3; DebugConfigDataHob->RamDebugInterface = 0; DebugConfigDataHob->UartDebugInterface = 0; DebugConfigDataHob->Usb3DebugInterface = 0; DebugConfigDataHob->SerialIoDebugInterface = (FeaturePcdGet (PcdSerialIoUartEnable)) ? 1 : 0; DebugConfigDataHob->TraceHubDebugInterface = 0; DEBUG_CODE_END(); return EFI_SUCCESS; } EFI_BOOT_MODE EFIAPI UpXtremeBoardBootModeDetect ( VOID ) { return BOOT_WITH_FULL_CONFIGURATION; }