diff options
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Reset/Common/PchResetCommon.c')
-rw-r--r-- | ReferenceCode/Chipset/LynxPoint/Reset/Common/PchResetCommon.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/Reset/Common/PchResetCommon.c b/ReferenceCode/Chipset/LynxPoint/Reset/Common/PchResetCommon.c new file mode 100644 index 0000000..4516b1f --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Reset/Common/PchResetCommon.c @@ -0,0 +1,254 @@ +/** @file + PCH RESET Common Library implements the Pch Reset Interface. + +@copyright + Copyright (c) 2011 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ +#include "PchReset.h" + +/** + Initialize an Pch Reset protocol instance. + The function will assert in debug if PCH RCBA has not been initialized + + @param[in] PchResetInstance Pointer to PchResetInstance to initialize + + @retval EFI_SUCCESS The protocol instance was properly initialized + @exception EFI_UNSUPPORTED The PCH is not supported by this module +**/ +EFI_STATUS +PchResetProtocolConstructor ( + PCH_RESET_INSTANCE *PchResetInstance + ) +{ + /// + /// Check if the current PCH is known and supported by this code + /// + if (!IsPchSupported ()) { + DEBUG ((EFI_D_ERROR, "PCH Reset Protocol not supported due to no proper PCH LPC found!\n")); + return EFI_UNSUPPORTED; + } + /// + /// Initialize the Reset protocol instance + /// + PchResetInstance->Signature = PCH_RESET_SIGNATURE; + PchResetInstance->Handle = NULL; + PchResetInstance->PchResetProtocol.Reset = PchReset; + + /// + /// Sanity check to ensure PCH RCBA initialization has occurred previously. + /// + PchResetInstance->PchRootComplexBar = PCH_RCRB_BASE; + ASSERT (PchResetInstance->PchRootComplexBar != 0); + + return EFI_SUCCESS; +} + +/** + Execute Pch Reset from the host controller. + + @param[in] This Pointer to the PCH_RESET_PROTOCOL instance. + @param[in] PchResetType Pch Reset Types which includes ColdReset, WarmReset, ShutdownReset, + PowerCycleReset, GlobalReset, GlobalResetWithEc + + @retval EFI_SUCCESS Successfully completed. + @retval EFI_INVALID_PARAMETER If ResetType is invalid. +**/ +EFI_STATUS +EFIAPI +PchReset ( + IN PCH_RESET_PROTOCOL *This, + IN PCH_RESET_TYPE PchResetType + ) +{ + PCH_RESET_INSTANCE *PchResetInstance; + UINTN PchRootComplexBar; + UINT16 PmBase; + UINT16 GpioBase; + UINT8 OutputData; + UINT32 Data32; + UINT16 Data16; + EFI_STATUS Status; + PCH_SERIES PchSeries; + + PchSeries = GetPchSeries(); + PchResetInstance = PCH_RESET_INSTANCE_FROM_THIS (This); + PchRootComplexBar = PchResetInstance->PchRootComplexBar; + PmBase = PciRead16 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE) + ) & B_PCH_LPC_ACPI_BASE_BAR; + + GpioBase = PciRead16 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_GPIO_BASE) + ) & B_PCH_LPC_GPIO_BASE_BAR; + + switch (PchResetType) { + case WarmReset: + IoWrite8 ((UINTN) R_PCH_RST_CNT, (UINT8) V_PCH_RST_CNT_SOFTSTARTSTATE); + OutputData = V_PCH_RST_CNT_SOFTRESET; + break; + + case ColdReset: + IoWrite8 ((UINTN) R_PCH_RST_CNT, (UINT8) V_PCH_RST_CNT_HARDSTARTSTATE); + +// AMI_OVERRIDE, [EIP81593] >>> +#ifdef COLD_RESET_WITH_POWER_CYCLE + OutputData = V_PCH_RST_CNT_FULLRESET; +#else + OutputData = V_PCH_RST_CNT_HARDRESET; +#endif +// AMI_OVERRIDE, [EIP81593] <<< + break; + + case ShutdownReset: + /// + /// Firstly, ACPI decode must be enabled + /// + PciOr8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_CNT), + (UINT8) (B_PCH_LPC_ACPI_CNT_ACPI_EN) + ); + + /// + /// Then, GPE0_EN should be disabled to avoid any GPI waking up the system from S5 + /// + if (PchSeries == PchLp) { + IoWrite32 ((UINTN) (PmBase + R_PCH_ACPI_GPE0_EN_127_96), 0); + } else if (PchSeries == PchH) { + IoWrite16 ((UINTN) (PmBase + R_PCH_ACPI_GPE0a_EN), 0); + IoWrite16 ((UINTN) (PmBase + R_PCH_ACPI_GPE0b_EN), 0); + } + + /// + /// Secondly, PwrSts register must be cleared + /// + /// Write a "1" to bit[8] of power button status register at + /// (PM_BASE + PM1_STS_OFFSET) to clear this bit + /// + Data16 = B_PCH_SMI_STS_PM1_STS_REG; +// AMI_OVERWRITE >>> EIP136638 + IoWrite16 ((UINTN) (PmBase + R_PCH_ACPI_PM1_STS), Data16); +// AMI_OVERWRITE <<< + + /// + /// Finally, transform system into S5 sleep state + /// + Data32 = IoRead32 ((UINTN) (PmBase + R_PCH_ACPI_PM1_CNT)); + + Data32 = (UINT32) ((Data32 &~(B_PCH_ACPI_PM1_CNT_SLP_TYP + B_PCH_ACPI_PM1_CNT_SLP_EN)) | V_PCH_ACPI_PM1_CNT_S5); + + IoWrite32 ((UINTN) (PmBase + R_PCH_ACPI_PM1_CNT), Data32); + + Data32 = Data32 | B_PCH_ACPI_PM1_CNT_SLP_EN; + + IoWrite32 ((UINTN) (PmBase + R_PCH_ACPI_PM1_CNT), Data32); + + return EFI_SUCCESS; + + case PowerCycleReset: + case GlobalReset: + case GlobalResetWithEc: + /// + /// PCH BIOS Spec Rev 0.5.0, Section 4.6 GPIO Reset Requirement + /// System BIOS is recommended to clear "GPIO Reset Select" registers [GP_RST_SEL1 (GPIOBASE + offset 60h), + /// GP_RST_SEL2 (GPIOBASE + offset 64h) and GP_RST_SEL3 (GPIOBASE + offset 68h)] before issuing a hard or + /// global reset unless specially requested by the platform designer. + /// + IoWrite32 ((UINTN) (GpioBase + R_PCH_GP_RST_SEL), 0); + IoWrite32 ((UINTN) (GpioBase + R_PCH_GP_RST_SEL2), 0); + IoWrite32 ((UINTN) (GpioBase + R_PCH_GP_RST_SEL3), 0); + + if ((PchResetType == GlobalReset) || (PchResetType == GlobalResetWithEc)) { + PciOr32 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_PMIR), + (UINT32) (B_PCH_LPC_PMIR_CF9GR) + ); + } + + if ((PchResetType == GlobalResetWithEc) && + ((MmioRead32 (PchRootComplexBar + R_PCH_RCRB_DEEP_S4_POL) & + (B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_AC | B_PCH_RCRB_DEEP_S4_POL_DPS4_EN_DC)) == 0) && + ((MmioRead32 (PchRootComplexBar + R_PCH_RCRB_DEEP_S5_POL) & + (B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_AC | B_PCH_RCRB_DEEP_S5_POL_DPS5_EN_DC)) == 0)) { + /// + /// PCH BIOS Spec Rev 0.5.0, Section 4.5 Global Reset + /// For systems with an embedded controller, System BIOS should also take these additional steps when it performs the Global Reset: + /// CF9h Global Reset: + /// + if (PchSeries == PchH) { + /// 1. Set GPIOBASE + offset 00h[30] = 1b (for non-Deep Sx enabled platforms) + /// 2. Set GPIOBASE + offset 04h[30] = 0b (for non-Deep Sx enabled platforms) + /// 3. Set GPIOBASE + offset 0Ch[30] = 0b (for non-Deep Sx enabled platforms) + /// 4. Set GPIOBASE + offset 60h[30] = 1b (for non-Deep Sx enabled platforms) + /// NOTE: For Deep Sx enabled platforms steps 1,2 and 3 should be skipped and pin should be left in native mode + /// 5. Set CF9GR bit, D31:F0:ACh[20], issue a Global Reset through a 0xCF9 write of either 06h or 0Eh commands. + /// Global Reset MEI Message + /// 1. BIOS makes sure GPIO30 is left in native mode (default mode) before sending a Global Reset MEI message. + /// + IoOr32 ((UINTN) (GpioBase + R_PCH_GPIO_USE_SEL), (UINT32) (BIT30)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GPIO_IO_SEL), (UINT32) (~BIT30)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GPIO_LVL), (UINT32) (~BIT30)); + } + + if (PchSeries == PchLp) { + /// 1. Set GPIOBASE + offset 1F0h[0] = 1b (for non-Deep Sx enabled platforms) + /// 2. Set GPIOBASE + offset 1F0h[2] = 0b (for non-Deep Sx enabled platforms) + /// 3. Set GPIOBASE + offset 1F0h[31] = 0b (for non-Deep Sx enabled platforms) + /// 4. Set GPIOBASE + offset 60h[30] = 1h (for non-Deep Sx enabled platforms) + /// NOTE: For Deep Sx enabled platforms steps 1,2 and 3 should be skipped and pin should be left in native mode + /// 5. Set CF9GR bit, D31:F0:ACh[20], issue a Global Reset through a 0xCF9 write of either 06h or 0Eh commands. + /// Global Reset MEI Message + /// 1. BIOS makes sure GPIO30 is left in native mode (default mode) before sending a Global Reset MEI message. + /// + IoOr32 ((UINTN) (GpioBase + R_PCH_GP_30_CONFIG0), (UINT32) (B_PCH_GPIO_OWN0_GPIO_USE_SEL)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GP_30_CONFIG0), (UINT32) (~B_PCH_GPIO_OWN0_GPIO_IO_SEL)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GP_30_CONFIG0), (UINT32) (~B_PCH_GPIO_OWN0_GPO_LVL)); + } + IoOr32 ((UINTN) (GpioBase + R_PCH_GP_RST_SEL), (UINT32) (BIT30)); + } + + OutputData = V_PCH_RST_CNT_FULLRESET; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + Status = PchResetCallback (PchResetType); + + if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) { + IoWrite8 ((UINTN) R_PCH_RST_CNT, OutputData); + /// + /// Waiting for system reset + /// + EFI_DEADLOOP (); + } + + return Status; +} |