summaryrefslogtreecommitdiff
path: root/ReferenceCode/Chipset/LynxPoint/Reset/Common/PchResetCommon.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Reset/Common/PchResetCommon.c')
-rw-r--r--ReferenceCode/Chipset/LynxPoint/Reset/Common/PchResetCommon.c254
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;
+}