Home | History | Annotate | Download | only in QNC
      1 /** @file
      2 File to contain all the hardware specific stuff for the Smm Sx dispatch protocol.
      3 
      4 Copyright (c) 2013-2015 Intel Corporation.
      5 
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 
     15 **/
     16 
     17 //
     18 // Include common header file for this module.
     19 //
     20 #include "CommonHeader.h"
     21 
     22 #include "QNCSmmHelpers.h"
     23 
     24 CONST QNC_SMM_SOURCE_DESC SX_SOURCE_DESC = {
     25   QNC_SMM_NO_FLAGS,
     26   {
     27     {
     28       {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIE}}, S_QNC_GPE0BLK_SMIE, N_QNC_GPE0BLK_SMIE_SLP
     29     },
     30     NULL_BIT_DESC_INITIALIZER
     31   },
     32   {
     33     {
     34       {GPE_ADDR_TYPE, {R_QNC_GPE0BLK_SMIS}}, S_QNC_GPE0BLK_SMIS, N_QNC_GPE0BLK_SMIS_SLP
     35     }
     36   }
     37 };
     38 
     39 VOID
     40 SxGetContext(
     41   IN  DATABASE_RECORD    *Record,
     42   OUT QNC_SMM_CONTEXT    *Context
     43   )
     44 {
     45   UINT32        Pm1Cnt;
     46 
     47   Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
     48 
     49   //
     50   // By design, the context phase will always be ENTRY
     51   //
     52   Context->Sx.Phase = SxEntry;
     53 
     54   //
     55   // Map the PM1_CNT register's SLP_TYP bits to the context type
     56   //
     57   switch (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) {
     58 
     59   case V_S0:
     60     Context->Sx.Type = SxS0;
     61     break;
     62 
     63   case V_S3:
     64     Context->Sx.Type = SxS3;
     65     break;
     66 
     67   case V_S4:
     68     Context->Sx.Type = SxS4;
     69     break;
     70 
     71   case V_S5:
     72     Context->Sx.Type = SxS5;
     73     break;
     74 
     75   default:
     76     ASSERT (FALSE);
     77     break;
     78   };
     79 }
     80 
     81 BOOLEAN
     82 SxCmpContext (
     83   IN QNC_SMM_CONTEXT     *Context1,
     84   IN QNC_SMM_CONTEXT     *Context2
     85   )
     86 {
     87   return (BOOLEAN)(Context1->Sx.Type == Context2->Sx.Type);
     88 }
     89 
     90 VOID
     91 QNCSmmSxGoToSleep(
     92   VOID
     93   )
     94 /*++
     95 
     96 Routine Description:
     97 
     98   When we get an SMI that indicates that we are transitioning to a sleep state,
     99   we need to actually transition to that state.  We do this by disabling the
    100   "SMI on sleep enable" feature, which generates an SMI when the operating system
    101   tries to put the system to sleep, and then physically putting the system to sleep.
    102 
    103 Returns:
    104 
    105   None.
    106 
    107 --*/
    108 {
    109   UINT32        Pm1Cnt;
    110 
    111   //
    112   // Flush cache into memory before we go to sleep. It is necessary for S3 sleep
    113   // because we may update memory in SMM Sx sleep handlers -- the updates are in cache now
    114   //
    115   AsmWbinvd();
    116 
    117   //
    118   // Disable SMIs
    119   //
    120   QNCSmmClearSource (&SX_SOURCE_DESC );
    121   QNCSmmDisableSource (&SX_SOURCE_DESC);
    122 
    123   //
    124   // Clear Sleep Type Enable
    125   //
    126   IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIE, (UINT16)(~B_QNC_GPE0BLK_SMIE_SLP));
    127 
    128   // clear sleep SMI status
    129   IoAnd16 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, (UINT16)(S_QNC_GPE0BLK_SMIS));
    130 
    131   //
    132   // Now that SMIs are disabled, write to the SLP_EN bit again to trigger the sleep
    133   //
    134   Pm1Cnt = IoOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, B_QNC_PM1BLK_PM1C_SLPEN);
    135 
    136   //
    137   // The system just went to sleep. If the sleep state was S1, then code execution will resume
    138   // here when the system wakes up.
    139   //
    140   Pm1Cnt = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
    141   if ((Pm1Cnt & B_QNC_PM1BLK_PM1C_SCIEN) == 0) {
    142     //
    143     // An ACPI OS isn't present, clear the sleep information
    144     //
    145     Pm1Cnt &= ~B_QNC_PM1BLK_PM1C_SLPTP;
    146     Pm1Cnt |= V_S0;
    147 
    148     IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Pm1Cnt);
    149   }
    150 
    151   QNCSmmClearSource (&SX_SOURCE_DESC);
    152   QNCSmmEnableSource (&SX_SOURCE_DESC);
    153 }
    154