]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / Smm / DxeSmm / QncSmmDispatcher / QNC / QNCSmmSx.c
diff --git a/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c b/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNC/QNCSmmSx.c
new file mode 100644 (file)
index 0000000..9d0de36
--- /dev/null
@@ -0,0 +1,153 @@
+/** @file\r
+File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "QNCSmmHelpers.h"\r
+\r
+CONST QNC_SMM_SOURCE_DESC SX_SOURCE_DESC = {\r
+  QNC_SMM_NO_FLAGS,\r
+  {\r
+    {\r
+      {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_SLP\r
+    },\r
+    NULL_BIT_DESC_INITIALIZER\r
+  },\r
+  {\r
+    {\r
+      {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_SLP\r
+    }\r
+  }\r
+};\r
+\r
+VOID\r
+SxGetContext(\r
+  IN  DATABASE_RECORD    *Record,\r
+  OUT QNC_SMM_CONTEXT    *Context\r
+  )\r
+{\r
+  UINT32        Pm1Cnt;\r
+\r
+  Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
+\r
+  //\r
+  // By design, the context phase will always be ENTRY\r
+  //\r
+  Context->Sx.Phase = SxEntry;\r
+\r
+  //\r
+  // Map the PM1_CNT register's SLP_TYP bits to the context type\r
+  //\r
+  switch (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) {\r
+\r
+  case V_S0:\r
+    Context->Sx.Type = SxS0;\r
+    break;\r
+\r
+  case V_S3:\r
+    Context->Sx.Type = SxS3;\r
+    break;\r
+\r
+  case V_S4:\r
+    Context->Sx.Type = SxS4;\r
+    break;\r
+\r
+  case V_S5:\r
+    Context->Sx.Type = SxS5;\r
+    break;\r
+\r
+  default:\r
+    ASSERT (FALSE);\r
+    break;\r
+  };\r
+}\r
+\r
+BOOLEAN\r
+SxCmpContext (\r
+  IN QNC_SMM_CONTEXT     *Context1,\r
+  IN QNC_SMM_CONTEXT     *Context2\r
+  )\r
+{\r
+  return (BOOLEAN)(Context1->Sx.Type == Context2->Sx.Type);\r
+}\r
+\r
+VOID\r
+QNCSmmSxGoToSleep(\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  When we get an SMI that indicates that we are transitioning to a sleep state,\r
+  we need to actually transition to that state.  We do this by disabling the\r
+  "SMI on sleep enable" feature, which generates an SMI when the operating system\r
+  tries to put the system to sleep, and then physically putting the system to sleep.\r
+\r
+Returns:\r
+\r
+  None.\r
+\r
+--*/\r
+{\r
+  UINT32        Pm1Cnt;\r
+\r
+  //\r
+  // Flush cache into memory before we go to sleep. It is necessary for S3 sleep\r
+  // because we may update memory in SMM Sx sleep handlers -- the updates are in cache now\r
+  //\r
+  AsmWbinvd();\r
+\r
+  //\r
+  // Disable SMIs\r
+  //\r
+  QNCSmmClearSource (&SX_SOURCE_DESC );\r
+  QNCSmmDisableSource (&SX_SOURCE_DESC);\r
+\r
+  //\r
+  // Clear Sleep Type Enable\r
+  //\r
+  IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIE, (UINT16)(~B_QNC_GPE0BLK_SMIE_SLP));\r
+\r
+  // clear sleep SMI status\r
+  IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, (UINT16)(S_QNC_GPE0BLK_SMIS));\r
+\r
+  //\r
+  // Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep\r
+  //\r
+  Pm1Cnt = IoOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, B_QNC_PM1BLK_PM1C_SLPEN);\r
+\r
+  //\r
+  // The system just went to sleep. If the sleep state was S1, then code execution will resume\r
+  // here when the system wakes up.\r
+  //\r
+  Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);\r
+  if ((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == 0) {\r
+    //\r
+    // An ACPI OS isn't present, clear the sleep information\r
+    //\r
+    Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SLPTP;\r
+    Pm1Cnt |= V_S0;\r
+\r
+    IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Pm1Cnt);\r
+  }\r
+\r
+  QNCSmmClearSource (&SX_SOURCE_DESC);\r
+  QNCSmmEnableSource (&SX_SOURCE_DESC);\r
+}\r